From 8c17c196e56064f8e200217e05090413f06bcb6a Mon Sep 17 00:00:00 2001 From: Wannes Malfait Date: Mon, 27 Feb 2023 16:19:12 +0100 Subject: [PATCH] Node Wrangler: apply autopep8 formatting The node wrangler source code wasn't consistently formatted before, which made it quite annoying to make changes. This formats it with the same formatter used for other python files in blender's source code, so that, in principle, the IDE would already be configured correctly for anyone working on blender. --- node_wrangler/__init__.py | 446 ++++++++++++++++++++++---------------- 1 file changed, 264 insertions(+), 182 deletions(-) diff --git a/node_wrangler/__init__.py b/node_wrangler/__init__.py index 757c80ba3..ec93a2be9 100644 --- a/node_wrangler/__init__.py +++ b/node_wrangler/__init__.py @@ -71,7 +71,7 @@ rl_outputs = ( RL_entry('use_pass_uv', 'UV', 'UV', True, True), RL_entry('use_pass_vector', 'Speed', 'Vector', False, True), RL_entry('use_pass_z', 'Z', 'Depth', True, True), - ) +) # list of blend types of "Mix" nodes in a form that can be used as 'items' for EnumProperty. # used list, not tuple for easy merging with other lists. @@ -192,11 +192,13 @@ draw_color_sets = { viewer_socket_name = "tmp_viewer" + def get_nodes_from_category(category_name, context): for category in node_categories_iter(context): if category.name == category_name: return sorted(category.items(context), key=lambda node: node.label) + def get_first_enabled_output(node): for output in node.outputs: if output.enabled: @@ -204,9 +206,11 @@ def get_first_enabled_output(node): else: return node.outputs[0] + def is_visible_socket(socket): return not socket.hide and socket.enabled and socket.type != 'CUSTOM' + def nice_hotkey_name(punc): # convert the ugly string name into the actual character nice_name = { @@ -329,12 +333,14 @@ def autolink(node1, node2, links): print("Could not make a link from " + node1.name + " to " + node2.name) return link_made + def abs_node_location(node): abs_location = node.location if node.parent is None: return abs_location return abs_location + abs_node_location(node.parent) + def node_at_pos(nodes, context, event): nodes_under_mouse = [] target_node = None @@ -395,17 +401,18 @@ def store_mouse_cursor(context, event): else: space.cursor_location = tree.view_center + def draw_line(x1, y1, x2, y2, size, colour=(1.0, 1.0, 1.0, 0.7)): shader = gpu.shader.from_builtin('POLYLINE_SMOOTH_COLOR') shader.uniform_float("viewportSize", gpu.state.viewport_get()[2:]) shader.uniform_float("lineWidth", size * prefs_line_width()) vertices = ((x1, y1), (x2, y2)) - vertex_colors = ((colour[0]+(1.0-colour[0])/4, - colour[1]+(1.0-colour[1])/4, - colour[2]+(1.0-colour[2])/4, - colour[3]+(1.0-colour[3])/4), - colour) + vertex_colors = ((colour[0] + (1.0 - colour[0]) / 4, + colour[1] + (1.0 - colour[1]) / 4, + colour[2] + (1.0 - colour[2]) / 4, + colour[3] + (1.0 - colour[3]) / 4), + colour) batch = batch_for_shader(shader, 'LINE_STRIP', {"pos": vertices, "color": vertex_colors}) batch.draw(shader) @@ -416,7 +423,7 @@ def draw_circle_2d_filled(mx, my, radius, colour=(1.0, 1.0, 1.0, 0.7)): sides = 12 vertices = [(radius * cos(i * 2 * pi / sides) + mx, radius * sin(i * 2 * pi / sides) + my) - for i in range(sides + 1)] + for i in range(sides + 1)] shader = gpu.shader.from_builtin('UNIFORM_COLOR') shader.uniform_float("color", colour) @@ -431,8 +438,8 @@ def draw_rounded_node_border(node, radius=8, colour=(1.0, 1.0, 1.0, 0.7)): nlocx, nlocy = abs_node_location(node) - nlocx = (nlocx+1) * dpi_fac() - nlocy = (nlocy+1) * dpi_fac() + nlocx = (nlocx + 1) * dpi_fac() + nlocy = (nlocy + 1) * dpi_fac() ndimx = node.dimensions.x ndimy = node.dimensions.y @@ -451,52 +458,52 @@ def draw_rounded_node_border(node, radius=8, colour=(1.0, 1.0, 1.0, 0.7)): # Top left corner mx, my = bpy.context.region.view2d.view_to_region(nlocx, nlocy, clip=False) - vertices = [(mx,my)] - for i in range(sides+1): - if (4<=i<=8): + vertices = [(mx, my)] + for i in range(sides + 1): + if (4 <= i <= 8): if mx < area_width: cosine = radius * cos(i * 2 * pi / sides) + mx sine = radius * sin(i * 2 * pi / sides) + my - vertices.append((cosine,sine)) + vertices.append((cosine, sine)) batch = batch_for_shader(shader, 'TRI_FAN', {"pos": vertices}) batch.draw(shader) # Top right corner mx, my = bpy.context.region.view2d.view_to_region(nlocx + ndimx, nlocy, clip=False) - vertices = [(mx,my)] - for i in range(sides+1): - if (0<=i<=4): + vertices = [(mx, my)] + for i in range(sides + 1): + if (0 <= i <= 4): if mx < area_width: cosine = radius * cos(i * 2 * pi / sides) + mx sine = radius * sin(i * 2 * pi / sides) + my - vertices.append((cosine,sine)) + vertices.append((cosine, sine)) batch = batch_for_shader(shader, 'TRI_FAN', {"pos": vertices}) batch.draw(shader) # Bottom left corner mx, my = bpy.context.region.view2d.view_to_region(nlocx, nlocy - ndimy, clip=False) - vertices = [(mx,my)] - for i in range(sides+1): - if (8<=i<=12): + vertices = [(mx, my)] + for i in range(sides + 1): + if (8 <= i <= 12): if mx < area_width: cosine = radius * cos(i * 2 * pi / sides) + mx sine = radius * sin(i * 2 * pi / sides) + my - vertices.append((cosine,sine)) + vertices.append((cosine, sine)) batch = batch_for_shader(shader, 'TRI_FAN', {"pos": vertices}) batch.draw(shader) # Bottom right corner mx, my = bpy.context.region.view2d.view_to_region(nlocx + ndimx, nlocy - ndimy, clip=False) - vertices = [(mx,my)] - for i in range(sides+1): - if (12<=i<=16): + vertices = [(mx, my)] + for i in range(sides + 1): + if (12 <= i <= 16): if mx < area_width: cosine = radius * cos(i * 2 * pi / sides) + mx sine = radius * sin(i * 2 * pi / sides) + my - vertices.append((cosine,sine)) + vertices.append((cosine, sine)) batch = batch_for_shader(shader, 'TRI_FAN', {"pos": vertices}) batch.draw(shader) @@ -510,10 +517,10 @@ def draw_rounded_node_border(node, radius=8, colour=(1.0, 1.0, 1.0, 0.7)): m1x, m1y = bpy.context.region.view2d.view_to_region(nlocx, nlocy, clip=False) m2x, m2y = bpy.context.region.view2d.view_to_region(nlocx, nlocy - ndimy, clip=False) if m1x < area_width and m2x < area_width: - vertices.extend([(m2x-radius,m2y), (m2x,m2y), - (m1x,m1y), (m1x-radius,m1y)]) - indices.extend([(id_last, id_last+1, id_last+3), - (id_last+3, id_last+1, id_last+2)]) + vertices.extend([(m2x - radius, m2y), (m2x, m2y), + (m1x, m1y), (m1x - radius, m1y)]) + indices.extend([(id_last, id_last + 1, id_last + 3), + (id_last + 3, id_last + 1, id_last + 2)]) id_last += 4 # Top edge @@ -521,37 +528,38 @@ def draw_rounded_node_border(node, radius=8, colour=(1.0, 1.0, 1.0, 0.7)): m2x, m2y = bpy.context.region.view2d.view_to_region(nlocx + ndimx, nlocy, clip=False) m1x = min(m1x, area_width) m2x = min(m2x, area_width) - vertices.extend([(m1x,m1y), (m2x,m1y), - (m2x,m1y+radius), (m1x,m1y+radius)]) - indices.extend([(id_last, id_last+1, id_last+3), - (id_last+3, id_last+1, id_last+2)]) + vertices.extend([(m1x, m1y), (m2x, m1y), + (m2x, m1y + radius), (m1x, m1y + radius)]) + indices.extend([(id_last, id_last + 1, id_last + 3), + (id_last + 3, id_last + 1, id_last + 2)]) id_last += 4 # Right edge m1x, m1y = bpy.context.region.view2d.view_to_region(nlocx + ndimx, nlocy, clip=False) m2x, m2y = bpy.context.region.view2d.view_to_region(nlocx + ndimx, nlocy - ndimy, clip=False) if m1x < area_width and m2x < area_width: - vertices.extend([(m1x,m2y), (m1x+radius,m2y), - (m1x+radius,m1y), (m1x,m1y)]) - indices.extend([(id_last, id_last+1, id_last+3), - (id_last+3, id_last+1, id_last+2)]) + vertices.extend([(m1x, m2y), (m1x + radius, m2y), + (m1x + radius, m1y), (m1x, m1y)]) + indices.extend([(id_last, id_last + 1, id_last + 3), + (id_last + 3, id_last + 1, id_last + 2)]) id_last += 4 # Bottom edge - m1x, m1y = bpy.context.region.view2d.view_to_region(nlocx, nlocy-ndimy, clip=False) - m2x, m2y = bpy.context.region.view2d.view_to_region(nlocx + ndimx, nlocy-ndimy, clip=False) + m1x, m1y = bpy.context.region.view2d.view_to_region(nlocx, nlocy - ndimy, clip=False) + m2x, m2y = bpy.context.region.view2d.view_to_region(nlocx + ndimx, nlocy - ndimy, clip=False) m1x = min(m1x, area_width) m2x = min(m2x, area_width) - vertices.extend([(m1x,m2y), (m2x,m2y), - (m2x,m1y-radius), (m1x,m1y-radius)]) - indices.extend([(id_last, id_last+1, id_last+3), - (id_last+3, id_last+1, id_last+2)]) + vertices.extend([(m1x, m2y), (m2x, m2y), + (m2x, m1y - radius), (m1x, m1y - radius)]) + indices.extend([(id_last, id_last + 1, id_last + 3), + (id_last + 3, id_last + 1, id_last + 2)]) # now draw all edges in one batch if len(vertices) != 0: batch = batch_for_shader(shader, 'TRIS', {"pos": vertices}, indices=indices) batch.draw(shader) + def draw_callback_nodeoutline(self, context, mode): if self.mouse_path: gpu.state.blend_set('ALPHA') @@ -602,6 +610,7 @@ def draw_callback_nodeoutline(self, context, mode): gpu.state.blend_set('NONE') + def get_active_tree(context): tree = context.space_data.node_tree path = [] @@ -616,16 +625,19 @@ def get_active_tree(context): path.append(tree) return tree, path + def get_nodes_links(context): tree, path = get_active_tree(context) return tree.nodes, tree.links + def is_viewer_socket(socket): # checks if a internal socket is a valid viewer socket return socket.name == viewer_socket_name and socket.NWViewerSocket + def get_internal_socket(socket): - #get the internal socket from a socket inside or outside the group + # get the internal socket from a socket inside or outside the group node = socket.node if node.type == 'GROUP_OUTPUT': source_iterator = node.inputs @@ -648,6 +660,7 @@ def get_internal_socket(socket): break return iterator[i] + def is_viewer_link(link, output_node): if link.to_node == output_node and link.to_socket == output_node.inputs[0]: return True @@ -657,11 +670,13 @@ def is_viewer_link(link, output_node): return True return False + def get_group_output_node(tree): for node in tree.nodes: - if node.type == 'GROUP_OUTPUT' and node.is_active_output == True: + if node.type == 'GROUP_OUTPUT' and node.is_active_output: return node + def get_output_location(tree): # get right-most location sorted_by_xloc = (sorted(tree.nodes, key=lambda x: x.location.x)) @@ -677,6 +692,8 @@ def get_output_location(tree): return loc_x, loc_y # Principled prefs + + class NWPrincipledPreferences(bpy.types.PropertyGroup): base_color: StringProperty( name='Base Color', @@ -732,6 +749,8 @@ class NWPrincipledPreferences(bpy.types.PropertyGroup): description='Naming Components for AO maps') # Addon prefs + + class NWNodeWrangler(bpy.types.AddonPreferences): bl_idname = __name__ @@ -779,7 +798,11 @@ class NWNodeWrangler(bpy.types.AddonPreferences): box = layout.box() col = box.column(align=True) - col.prop(self, "show_principled_lists", text='Edit tags for auto texture detection in Principled BSDF setup', toggle=True) + col.prop( + self, + "show_principled_lists", + text='Edit tags for auto texture detection in Principled BSDF setup', + toggle=True) if self.show_principled_lists: tags = self.principled_tags @@ -823,7 +846,6 @@ class NWNodeWrangler(bpy.types.AddonPreferences): row.label(text=keystr) - def nw_check(context): space = context.space_data valid_trees = ["ShaderNodeTree", "CompositorNodeTree", "TextureNodeTree", "GeometryNodeTree"] @@ -836,6 +858,7 @@ def nw_check(context): return False + class NWBase: @classmethod def poll(cls, context): @@ -908,7 +931,8 @@ class NWLazyMix(Operator, NWBase): args = (self, context, 'MIX') # Add the region OpenGL drawing callback # draw in view space with 'POST_VIEW' and 'PRE_VIEW' - self._handle = bpy.types.SpaceNodeEditor.draw_handler_add(draw_callback_nodeoutline, args, 'WINDOW', 'POST_PIXEL') + self._handle = bpy.types.SpaceNodeEditor.draw_handler_add( + draw_callback_nodeoutline, args, 'WINDOW', 'POST_PIXEL') self.mouse_path = [] @@ -966,7 +990,7 @@ class NWLazyConnect(Operator, NWBase): original_sel = [] original_unsel = [] for node in nodes: - if node.select == True: + if node.select: node.select = False original_sel.append(node) else: @@ -1013,7 +1037,8 @@ class NWLazyConnect(Operator, NWBase): args = (self, context, mode) # Add the region OpenGL drawing callback # draw in view space with 'POST_VIEW' and 'PRE_VIEW' - self._handle = bpy.types.SpaceNodeEditor.draw_handler_add(draw_callback_nodeoutline, args, 'WINDOW', 'POST_PIXEL') + self._handle = bpy.types.SpaceNodeEditor.draw_handler_add( + draw_callback_nodeoutline, args, 'WINDOW', 'POST_PIXEL') self.mouse_path = [] @@ -1030,13 +1055,19 @@ class NWDeleteUnused(Operator, NWBase): bl_label = 'Delete Unused Nodes' bl_options = {'REGISTER', 'UNDO'} - delete_muted: BoolProperty(name="Delete Muted", description="Delete (but reconnect, like Ctrl-X) all muted nodes", default=True) - delete_frames: BoolProperty(name="Delete Empty Frames", description="Delete all frames that have no nodes inside them", default=True) + delete_muted: BoolProperty( + name="Delete Muted", + description="Delete (but reconnect, like Ctrl-X) all muted nodes", + default=True) + delete_frames: BoolProperty( + name="Delete Empty Frames", + description="Delete all frames that have no nodes inside them", + default=True) def is_unused_node(self, node): - end_types = ['OUTPUT_MATERIAL', 'OUTPUT', 'VIEWER', 'COMPOSITE', \ - 'SPLITVIEWER', 'OUTPUT_FILE', 'LEVELS', 'OUTPUT_LIGHT', \ - 'OUTPUT_WORLD', 'GROUP_INPUT', 'GROUP_OUTPUT', 'FRAME'] + end_types = ['OUTPUT_MATERIAL', 'OUTPUT', 'VIEWER', 'COMPOSITE', + 'SPLITVIEWER', 'OUTPUT_FILE', 'LEVELS', 'OUTPUT_LIGHT', + 'OUTPUT_WORLD', 'GROUP_INPUT', 'GROUP_OUTPUT', 'FRAME'] if node.type in end_types: return False @@ -1059,7 +1090,7 @@ class NWDeleteUnused(Operator, NWBase): # Store selection selection = [] for node in nodes: - if node.select == True: + if node.select: selection.append(node.name) for node in nodes: @@ -1176,12 +1207,14 @@ class NWSwapLinks(Operator, NWBase): try: links.new(n2.outputs[connection[0]], connection[1]) except: - self.report({'WARNING'}, "Some connections have been lost due to differing numbers of output sockets") + self.report({'WARNING'}, + "Some connections have been lost due to differing numbers of output sockets") for connection in n2_outputs: try: links.new(n1.outputs[connection[0]], connection[1]) except: - self.report({'WARNING'}, "Some connections have been lost due to differing numbers of output sockets") + self.report({'WARNING'}, + "Some connections have been lost due to differing numbers of output sockets") else: if n1.outputs or n2.outputs: self.report({'WARNING'}, "One of the nodes has no outputs!") @@ -1195,14 +1228,14 @@ class NWSwapLinks(Operator, NWBase): return {'FINISHED'} if n1.inputs: types = [] - i=0 + i = 0 for i1 in n1.inputs: if i1.is_linked and not i1.is_multi_input: similar_types = 0 for i2 in n1.inputs: if i1.type == i2.type and i2.is_linked and not i2.is_multi_input: similar_types += 1 - types.append ([i1, similar_types, i]) + types.append([i1, similar_types, i]) i += 1 types.sort(key=lambda k: k[1], reverse=True) @@ -1223,7 +1256,7 @@ class NWSwapLinks(Operator, NWBase): fs = t[0].links[0].from_socket i = t[2] links.remove(t[0].links[0]) - if i+1 == len(n1.inputs): + if i + 1 == len(n1.inputs): i = -1 i += 1 while n1.inputs[i].is_linked: @@ -1281,6 +1314,7 @@ class NWAddAttrNode(Operator, NWBase): nodes.active.attribute_name = self.attr_name return {'FINISHED'} + class NWPreviewNode(Operator, NWBase): bl_idname = "node.nw_preview_node" bl_label = "Preview Node" @@ -1308,24 +1342,24 @@ class NWPreviewNode(Operator, NWBase): return False def ensure_viewer_socket(self, node, socket_type, connect_socket=None): - #check if a viewer output already exists in a node group otherwise create + # check if a viewer output already exists in a node group otherwise create if hasattr(node, "node_tree"): index = None if len(node.node_tree.outputs): free_socket = None for i, socket in enumerate(node.node_tree.outputs): if is_viewer_socket(socket) and is_visible_socket(node.outputs[i]) and socket.type == socket_type: - #if viewer output is already used but leads to the same socket we can still use it + # if viewer output is already used but leads to the same socket we can still use it is_used = self.is_socket_used_other_mats(socket) if is_used: - if connect_socket == None: + if connect_socket is None: continue groupout = get_group_output_node(node.node_tree) groupout_input = groupout.inputs[i] links = groupout_input.links if connect_socket not in [link.from_socket for link in links]: continue - index=i + index = i break if not free_socket: free_socket = i @@ -1333,7 +1367,7 @@ class NWPreviewNode(Operator, NWBase): index = free_socket if not index: - #create viewer socket + # create viewer socket node.node_tree.outputs.new(socket_type, viewer_socket_name) index = len(node.node_tree.outputs) - 1 node.node_tree.outputs[index].NWViewerSocket = True @@ -1354,12 +1388,12 @@ class NWPreviewNode(Operator, NWBase): def get_shader_output_node(self, tree): for node in tree.nodes: - if node.type == self.shader_output_type and node.is_active_output == True: + if node.type == self.shader_output_type and node.is_active_output: return node @classmethod def ensure_group_output(cls, tree): - #check if a group output node exists otherwise create + # check if a group output node exists otherwise create groupout = get_group_output_node(tree) if not groupout: groupout = tree.nodes.new('NodeGroupOutput') @@ -1388,7 +1422,7 @@ class NWPreviewNode(Operator, NWBase): socket = next_node.node_tree.outputs[socket_index] if is_viewer_socket(socket) and socket not in sockets: sockets.append(socket) - #continue search inside of node group but restrict socket to where we came from + # continue search inside of node group but restrict socket to where we came from groupout = get_group_output_node(next_node.node_tree) cls.search_sockets(groupout, sockets, index=socket_index) @@ -1405,12 +1439,12 @@ class NWPreviewNode(Operator, NWBase): cls.scan_nodes(node.node_tree, sockets) def link_leads_to_used_socket(self, link): - #return True if link leads to a socket that is already used in this material + # return True if link leads to a socket that is already used in this material socket = get_internal_socket(link.to_socket) return (socket and self.is_socket_used_active_mat(socket)) def is_socket_used_active_mat(self, socket): - #ensure used sockets in active material is calculated and check given socket + # ensure used sockets in active material is calculated and check given socket if not hasattr(self, "used_viewer_sockets_active_mat"): self.used_viewer_sockets_active_mat = [] materialout = self.get_shader_output_node(bpy.context.space_data.node_tree) @@ -1419,7 +1453,7 @@ class NWPreviewNode(Operator, NWBase): return socket in self.used_viewer_sockets_active_mat def is_socket_used_other_mats(self, socket): - #ensure used sockets in other materials are calculated and check given socket + # ensure used sockets in other materials are calculated and check given socket if not hasattr(self, "used_viewer_sockets_other_mats"): self.used_viewer_sockets_other_mats = [] for mat in bpy.data.materials: @@ -1493,7 +1527,7 @@ class NWPreviewNode(Operator, NWBase): socket_type = 'GEOMETRY' # Find an input socket of the output of type geometry geometryoutindex = None - for i,inp in enumerate(geometryoutput.inputs): + for i, inp in enumerate(geometryoutput.inputs): if inp.type == socket_type: geometryoutindex = i break @@ -1510,7 +1544,8 @@ class NWPreviewNode(Operator, NWBase): link_end = output_socket while tree.nodes.active != active: node = tree.nodes.active - index = self.ensure_viewer_socket(node,'NodeSocketGeometry', connect_socket=active.outputs[out_i] if node.node_tree.nodes.active == active else None) + index = self.ensure_viewer_socket( + node, 'NodeSocketGeometry', connect_socket=active.outputs[out_i] if node.node_tree.nodes.active == active else None) link_start = node.outputs[index] node_socket = node.node_tree.outputs[index] if node_socket in delete_sockets: @@ -1531,7 +1566,6 @@ class NWPreviewNode(Operator, NWBase): force_update(context) return {'FINISHED'} - # What follows is code for the shader editor output_types = [x.nodetype for x in get_nodes_from_category('Output', context)] @@ -1547,7 +1581,7 @@ class NWPreviewNode(Operator, NWBase): materialout = None # placeholder node delete_sockets = [] - #scan through all nodes in tree including nodes inside of groups to find viewer sockets + # scan through all nodes in tree including nodes inside of groups to find viewer sockets self.scan_nodes(base_node_tree, delete_sockets) materialout = self.get_shader_output_node(base_node_tree) @@ -1586,7 +1620,8 @@ class NWPreviewNode(Operator, NWBase): link_end = output_socket while tree.nodes.active != active: node = tree.nodes.active - index = self.ensure_viewer_socket(node, socket_type, connect_socket=active.outputs[out_i] if node.node_tree.nodes.active == active else None) + index = self.ensure_viewer_socket( + node, socket_type, connect_socket=active.outputs[out_i] if node.node_tree.nodes.active == active else None) link_start = node.outputs[index] node_socket = node.node_tree.outputs[index] if node_socket in delete_sockets: @@ -1649,7 +1684,7 @@ class NWFrameSelected(Operator, NWBase): nodes, links = get_nodes_links(context) selected = [] for node in nodes: - if node.select == True: + if node.select: selected.append(node) bpy.ops.node.add_node(type='NodeFrame') @@ -1715,7 +1750,7 @@ class NWSwitchNodeType(Operator, NWBase): to_type: StringProperty( name="Switch to type", - default = '', + default='', ) def execute(self, context): @@ -1783,8 +1818,10 @@ class NWSwitchNodeType(Operator, NWBase): for the_type in types_order_one: if socket.type == the_type: # create values for sockets['INPUTS'][the_type] and sockets['OUTPUTS'][the_type] - # entry structure: (index_in_type, socket_index, socket_name, socket_default_value, socket_links) - sockets[in_out_name][the_type].append((len(sockets[in_out_name][the_type]), i, the_name, dval, socket_links)) + # entry structure: (index_in_type, socket_index, socket_name, + # socket_default_value, socket_links) + sockets[in_out_name][the_type].append( + (len(sockets[in_out_name][the_type]), i, the_name, dval, socket_links)) # Check which of the types in inputs/outputs is considered to be "main". # Set values of sockets['INPUTS']['MAIN'] and sockets['OUTPUTS']['MAIN'] for type_check in types_order_one: @@ -1903,7 +1940,7 @@ class NWMergeNodes(Operator, NWBase): mode: EnumProperty( name="mode", description="All possible blend types, boolean operations and math operations", - items= blend_types + [op for op in geo_combine_operations if op not in blend_types] + [op for op in operations if op not in blend_types], + items=blend_types + [op for op in geo_combine_operations if op not in blend_types] + [op for op in operations if op not in blend_types], ) merge_type: EnumProperty( name="merge type", @@ -1925,7 +1962,7 @@ class NWMergeNodes(Operator, NWBase): # in selected_nodes, it returns False. The depth is used to prevent # getting stuck in a loop because of an already present cycle. @staticmethod - def link_creates_cycle(link, selected_nodes, depth=0)->bool: + def link_creates_cycle(link, selected_nodes, depth=0) -> bool: if depth > 255: # We're stuck in a cycle, but that cycle was already present, # so we return False. @@ -1939,7 +1976,7 @@ class NWMergeNodes(Operator, NWBase): for output in node.outputs: if output.is_linked: for olink in output.links: - if NWMergeNodes.link_creates_cycle(olink, selected_nodes, depth+1): + if NWMergeNodes.link_creates_cycle(olink, selected_nodes, depth + 1): return True # None of the outputs found a node in selected_nodes, so there is no cycle. return False @@ -1949,14 +1986,14 @@ class NWMergeNodes(Operator, NWBase): # be connected. The last one is assumed to be a multi input socket. # For convenience the node is returned. @staticmethod - def merge_with_multi_input(nodes_list, merge_position,do_hide, loc_x, links, nodes, node_name, socket_indices): + def merge_with_multi_input(nodes_list, merge_position, do_hide, loc_x, links, nodes, node_name, socket_indices): # The y-location of the last node loc_y = nodes_list[-1][2] if merge_position == 'CENTER': # Average the y-location - for i in range(len(nodes_list)-1): + for i in range(len(nodes_list) - 1): loc_y += nodes_list[i][2] - loc_y = loc_y/len(nodes_list) + loc_y = loc_y / len(nodes_list) new_node = nodes.new(node_name) new_node.hide = do_hide new_node.location.x = loc_x @@ -1964,12 +2001,14 @@ class NWMergeNodes(Operator, NWBase): selected_nodes = [nodes[node_info[0]] for node_info in nodes_list] prev_links = [] outputs_for_multi_input = [] - for i,node in enumerate(selected_nodes): + for i, node in enumerate(selected_nodes): node.select = False # Search for the first node which had output links that do not create # a cycle, which we can then reconnect afterwards. if prev_links == [] and node.outputs[0].is_linked: - prev_links = [link for link in node.outputs[0].links if not NWMergeNodes.link_creates_cycle(link, selected_nodes)] + prev_links = [ + link for link in node.outputs[0].links if not NWMergeNodes.link_creates_cycle( + link, selected_nodes)] # Get the index of the socket, the last one is a multi input, and is thus used repeatedly # To get the placement to look right we need to reverse the order in which we connect the # outputs to the multi input socket. @@ -2025,9 +2064,9 @@ class NWMergeNodes(Operator, NWBase): node_type = 'ShaderNode' selected_mix = [] # entry = [index, loc] selected_shader = [] # entry = [index, loc] - selected_geometry = [] # entry = [index, loc] + selected_geometry = [] # entry = [index, loc] selected_math = [] # entry = [index, loc] - selected_vector = [] # entry = [index, loc] + selected_vector = [] # entry = [index, loc] selected_z = [] # entry = [index, loc] selected_alphaover = [] # entry = [index, loc] @@ -2081,7 +2120,14 @@ class NWMergeNodes(Operator, NWBase): if selected_mix and selected_math and merge_type == 'AUTO': selected_mix += selected_math selected_math = [] - for nodes_list in [selected_mix, selected_shader, selected_geometry, selected_math, selected_vector, selected_z, selected_alphaover]: + for nodes_list in [ + selected_mix, + selected_shader, + selected_geometry, + selected_math, + selected_vector, + selected_z, + selected_alphaover]: if not nodes_list: continue count_before = len(nodes) @@ -2100,8 +2146,9 @@ class NWMergeNodes(Operator, NWBase): else: node_type = 'GeometryNode' if merge_position == 'CENTER': - loc_y = ((nodes_list[len(nodes_list) - 1][2]) + (nodes_list[len(nodes_list) - 2][2])) / 2 # average yloc of last two nodes (lowest two) - if nodes_list[len(nodes_list) - 1][-1] == True: # if last node is hidden, mix should be shifted up a bit + # 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 if do_hide: loc_y += 40 else: @@ -2171,11 +2218,13 @@ class NWMergeNodes(Operator, NWBase): elif nodes_list == selected_geometry: if mode in ('JOIN', 'MIX'): add_type = node_type + 'JoinGeometry' - add = self.merge_with_multi_input(nodes_list, merge_position, do_hide, loc_x, links, nodes, add_type,[0]) + 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' - 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) + 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) add.operation = mode was_multi = True break @@ -2221,7 +2270,8 @@ class NWMergeNodes(Operator, NWBase): # "last" node has been added as first, so its index is count_before. last_add = nodes[count_before] # Create list of invalid indexes. - invalid_nodes = [nodes[n[0]] for n in (selected_mix + selected_math + selected_shader + selected_z + selected_geometry)] + invalid_nodes = [nodes[n[0]] + for n in (selected_mix + selected_math + selected_shader + selected_z + selected_geometry)] # Special case: # Two nodes were selected and first selected has no output links, second selected has output links. @@ -2299,7 +2349,7 @@ class NWBatchChangeNodes(Operator, NWBase): operation = self.operation for node in context.selected_nodes: if node.type == 'MIX_RGB' or (node.bl_idname == 'ShaderNodeMix' and node.data_type == 'RGBA'): - if not blend_type in [nav[0] for nav in navs]: + if blend_type not in [nav[0] for nav in navs]: node.blend_type = blend_type else: if blend_type == 'NEXT': @@ -2318,7 +2368,7 @@ class NWBatchChangeNodes(Operator, NWBase): node.blend_type = blend_types[index - 1][0] if node.type == 'MATH' or node.bl_idname == 'ShaderNodeMath': - if not operation in [nav[0] for nav in navs]: + if operation not in [nav[0] for nav in navs]: node.operation = operation else: if operation == 'NEXT': @@ -2414,7 +2464,11 @@ class NWCopySettings(Operator, NWBase): # Report nodes that are not valid valid_node_names = [n.name for n in valid_nodes] not_valid_names = list(set(selected_node_names) - set(valid_node_names)) - self.report({'INFO'}, "Ignored {} (not of the same type as {})".format(", ".join(not_valid_names), node_active.name)) + self.report( + {'INFO'}, + "Ignored {} (not of the same type as {})".format( + ", ".join(not_valid_names), + node_active.name)) # Reference original orig = node_active @@ -2479,7 +2533,11 @@ class NWCopySettings(Operator, NWBase): orig.select = True node_tree.nodes.active = orig - self.report({'INFO'}, "Successfully copied attributes from {} to: {}".format(orig.name, ", ".join(success_names))) + self.report( + {'INFO'}, + "Successfully copied attributes from {} to: {}".format( + orig.name, + ", ".join(success_names))) return {'FINISHED'} @@ -2587,7 +2645,10 @@ class NWAddTextureSetup(Operator, NWBase): bl_description = "Add Texture Node Setup to Selected Shaders" bl_options = {'REGISTER', 'UNDO'} - add_mapping: BoolProperty(name="Add Mapping Nodes", description="Create coordinate and mapping nodes for the texture (ignored for selected texture nodes)", default=True) + add_mapping: BoolProperty( + name="Add Mapping Nodes", + description="Create coordinate and mapping nodes for the texture (ignored for selected texture nodes)", + default=True) @classmethod def poll(cls, context): @@ -2728,23 +2789,23 @@ class NWAddPrincipledSetup(Operator, NWBase, ImportHelper): gloss_abbr = tags.gloss.split(' ') rough_abbr = tags.rough.split(' ') socketnames = [ - ['Displacement', tags.displacement.split(' '), None], - ['Base Color', tags.base_color.split(' '), None], - ['Subsurface Color', tags.sss_color.split(' '), None], - ['Metallic', tags.metallic.split(' '), None], - ['Specular', tags.specular.split(' '), None], - ['Roughness', rough_abbr + gloss_abbr, None], - ['Normal', normal_abbr + bump_abbr, None], - ['Transmission', tags.transmission.split(' '), None], - ['Emission', tags.emission.split(' '), None], - ['Alpha', tags.alpha.split(' '), None], - ['Ambient Occlusion', tags.ambient_occlusion.split(' '), None], + ['Displacement', tags.displacement.split(' '), None], + ['Base Color', tags.base_color.split(' '), None], + ['Subsurface Color', tags.sss_color.split(' '), None], + ['Metallic', tags.metallic.split(' '), None], + ['Specular', tags.specular.split(' '), None], + ['Roughness', rough_abbr + gloss_abbr, None], + ['Normal', normal_abbr + bump_abbr, None], + ['Transmission', tags.transmission.split(' '), None], + ['Emission', tags.emission.split(' '), None], + ['Alpha', tags.alpha.split(' '), None], + ['Ambient Occlusion', tags.ambient_occlusion.split(' '), None], ] match_files_to_socket_names(self.files, socketnames) # Remove socketnames without found files socketnames = [s for s in socketnames if s[2] - and path.exists(self.directory+s[2])] + and path.exists(self.directory + s[2])] if not socketnames: self.report({'INFO'}, 'No matching images found') print('No matching images found') @@ -2891,7 +2952,8 @@ class NWAddPrincipledSetup(Operator, NWBase, ImportHelper): # If more than one texture add reroute node in between reroute = nodes.new(type='NodeReroute') texture_nodes.append(reroute) - tex_coords = Vector((texture_nodes[0].location.x, sum(n.location.y for n in texture_nodes)/len(texture_nodes))) + tex_coords = Vector((texture_nodes[0].location.x, + sum(n.location.y for n in texture_nodes) / len(texture_nodes))) reroute.location = tex_coords + Vector((-50, -120)) for texture_node in texture_nodes: link = links.new(texture_node.inputs[0], reroute.outputs[0]) @@ -3131,7 +3193,8 @@ class NWAlignNodes(Operator, NWBase): active_loc = copy(nodes.active.location) # make a copy, not a reference # Check if nodes should be laid out horizontally or vertically - x_locs = [n.location.x + (n.dimensions.x / 2) for n in selection] # use dimension to get center of node, not corner + # use dimension to get center of node, not corner + x_locs = [n.location.x + (n.dimensions.x / 2) for n in selection] y_locs = [n.location.y - (n.dimensions.y / 2) for n in selection] x_range = max(x_locs) - min(x_locs) y_range = max(y_locs) - min(y_locs) @@ -3166,7 +3229,8 @@ class NWAlignNodes(Operator, NWBase): for node in selection: node.location += active_loc_diff else: # Position nodes centered around where they used to be - locs = ([n.location.x + (n.dimensions.x / 2) for n in selection]) if horizontal else ([n.location.y - (n.dimensions.y / 2) for n in selection]) + locs = ([n.location.x + (n.dimensions.x / 2) for n in selection] + ) if horizontal else ([n.location.y - (n.dimensions.y / 2) for n in selection]) new_mid = (max(locs) + min(locs)) / 2 for node in selection: if horizontal: @@ -3252,8 +3316,8 @@ class NWLinkToOutputNode(Operator): active = nodes.active output_index = None tree_type = context.space_data.tree_type - shader_outputs = {'OBJECT': 'ShaderNodeOutputMaterial', - 'WORLD': 'ShaderNodeOutputWorld', + shader_outputs = {'OBJECT': 'ShaderNodeOutputMaterial', + 'WORLD': 'ShaderNodeOutputWorld', 'LINESTYLE': 'ShaderNodeOutputLineStyle'} output_type = { 'ShaderNodeTree': shader_outputs[context.space_data.shader_type], @@ -3394,24 +3458,23 @@ class NWAddSequence(Operator, NWBase, ImportHelper): if not files[0].name and not filename: self.report({'ERROR'}, "No file chosen") return {'CANCELLED'} - elif files[0].name and (not filename or not path.exists(directory+filename)): + elif files[0].name and (not filename or not path.exists(directory + filename)): # User has selected multiple files without an active one, or the active one is non-existent filename = files[0].name - if not path.exists(directory+filename): - self.report({'ERROR'}, filename+" does not exist!") + if not path.exists(directory + filename): + self.report({'ERROR'}, filename + " does not exist!") return {'CANCELLED'} without_ext = '.'.join(filename.split('.')[:-1]) # if last digit isn't a number, it's not a sequence if not without_ext[-1].isdigit(): - self.report({'ERROR'}, filename+" does not seem to be part of a sequence") + self.report({'ERROR'}, filename + " does not seem to be part of a sequence") return {'CANCELLED'} - extension = filename.split('.')[-1] - reverse = without_ext[::-1] # reverse string + reverse = without_ext[::-1] # reverse string count_numbers = 0 for char in reverse: @@ -3420,9 +3483,9 @@ class NWAddSequence(Operator, NWBase, ImportHelper): else: break - without_num = without_ext[:count_numbers*-1] + without_num = without_ext[:count_numbers * -1] - files = sorted(glob(directory + without_num + "[0-9]"*count_numbers + "." + extension)) + files = sorted(glob(directory + without_num + "[0-9]" * count_numbers + "." + extension)) num_frames = len(files) @@ -3434,18 +3497,18 @@ class NWAddSequence(Operator, NWBase, ImportHelper): for node in nodes: node.select = False yloc += node_mid_pt(node, 'y') - yloc = yloc/len(nodes) + yloc = yloc / len(nodes) else: xloc = 0 yloc = 0 - name_with_hashes = without_num + "#"*count_numbers + '.' + extension + name_with_hashes = without_num + "#" * count_numbers + '.' + extension bpy.ops.node.add_node('INVOKE_DEFAULT', use_transform=True, type=node_type) node = nodes.active node.label = name_with_hashes - filepath = directory+(without_ext+'.'+extension) + filepath = directory + (without_ext + '.' + extension) if self.relative_path: if bpy.data.filepath: try: @@ -3458,7 +3521,8 @@ class NWAddSequence(Operator, NWBase, ImportHelper): img.name = name_with_hashes node.image = img image_user = node.image_user if tree.type == 'SHADER' else node - image_user.frame_offset = int(files[0][len(without_num)+len(directory):-1*(len(extension)+1)]) - 1 # separate the number from the file name of the first file + # separate the number from the file name of the first file + image_user.frame_offset = int(files[0][len(without_num) + len(directory):-1 * (len(extension) + 1)]) - 1 image_user.frame_duration = num_frames return {'FINISHED'} @@ -3480,7 +3544,7 @@ class NWAddMultipleImages(Operator, NWBase, ImportHelper): def execute(self, context): nodes, links = get_nodes_links(context) - xloc, yloc = context.region.view2d.region_to_view(context.area.width/2, context.area.height/2) + xloc, yloc = context.region.view2d.region_to_view(context.area.width / 2, context.area.height / 2) if context.space_data.node_tree.type == 'SHADER': node_type = "ShaderNodeTexImage" @@ -3503,7 +3567,7 @@ class NWAddMultipleImages(Operator, NWBase, ImportHelper): node.location.y = yloc yloc -= 40 - img = bpy.data.images.load(self.directory+fname) + img = bpy.data.images.load(self.directory + fname) node.image = img # shift new nodes up to center of tree @@ -3511,7 +3575,7 @@ class NWAddMultipleImages(Operator, NWBase, ImportHelper): for node in nodes: if node in new_nodes: node.select = True - node.location.y += (list_size/2) + node.location.y += (list_size / 2) else: node.select = False return {'FINISHED'} @@ -3535,7 +3599,7 @@ class NWViewerFocus(bpy.types.Operator): def invoke(self, context, event): render = context.scene.render space = context.space_data - percent = render.resolution_percentage*0.01 + percent = render.resolution_percentage * 0.01 nodes, links = get_nodes_links(context) viewers = [n for n in nodes if n.type == 'VIEWER'] @@ -3545,11 +3609,11 @@ class NWViewerFocus(bpy.types.Operator): mlocy = event.mouse_region_y select_node = bpy.ops.node.select(location=(mlocx, mlocy), extend=False) - if not 'FINISHED' in select_node: # only run if we're not clicking on a node + if 'FINISHED' not in select_node: # only run if we're not clicking on a node region_x = context.region.width region_y = context.region.height - region_center_x = context.region.width / 2 + region_center_x = context.region.width / 2 region_center_y = context.region.height / 2 bd_x = render.resolution_x * percent * space.backdrop_zoom @@ -3579,21 +3643,21 @@ class NWSaveViewer(bpy.types.Operator, ExportHelper): bl_label = "Save This Image" filepath: StringProperty(subtype="FILE_PATH") filename_ext: EnumProperty( - name="Format", - description="Choose the file format to save to", - items=(('.bmp', "BMP", ""), - ('.rgb', 'IRIS', ""), - ('.png', 'PNG', ""), - ('.jpg', 'JPEG', ""), - ('.jp2', 'JPEG2000', ""), - ('.tga', 'TARGA', ""), - ('.cin', 'CINEON', ""), - ('.dpx', 'DPX', ""), - ('.exr', 'OPEN_EXR', ""), - ('.hdr', 'HDR', ""), - ('.tif', 'TIFF', "")), - default='.png', - ) + name="Format", + description="Choose the file format to save to", + items=(('.bmp', "BMP", ""), + ('.rgb', 'IRIS', ""), + ('.png', 'PNG', ""), + ('.jpg', 'JPEG', ""), + ('.jp2', 'JPEG2000', ""), + ('.tga', 'TARGA', ""), + ('.cin', 'CINEON', ""), + ('.dpx', 'DPX', ""), + ('.exr', 'OPEN_EXR', ""), + ('.hdr', 'HDR', ""), + ('.tif', 'TIFF', "")), + default='.png', + ) @classmethod def poll(cls, context): @@ -3609,19 +3673,19 @@ class NWSaveViewer(bpy.types.Operator, ExportHelper): fp = self.filepath if fp: formats = { - '.bmp': 'BMP', - '.rgb': 'IRIS', - '.png': 'PNG', - '.jpg': 'JPEG', - '.jpeg': 'JPEG', - '.jp2': 'JPEG2000', - '.tga': 'TARGA', - '.cin': 'CINEON', - '.dpx': 'DPX', - '.exr': 'OPEN_EXR', - '.hdr': 'HDR', - '.tiff': 'TIFF', - '.tif': 'TIFF'} + '.bmp': 'BMP', + '.rgb': 'IRIS', + '.png': 'PNG', + '.jpg': 'JPEG', + '.jpeg': 'JPEG', + '.jp2': 'JPEG2000', + '.tga': 'TARGA', + '.cin': 'CINEON', + '.dpx': 'DPX', + '.exr': 'OPEN_EXR', + '.hdr': 'HDR', + '.tiff': 'TIFF', + '.tif': 'TIFF'} basename, ext = path.splitext(fp) old_render_format = context.scene.render.image_settings.file_format context.scene.render.image_settings.file_format = formats[self.filename_ext] @@ -3647,7 +3711,7 @@ class NWResetNodes(bpy.types.Operator): def execute(self, context): node_active = context.active_node node_selected = context.selected_nodes - node_ignore = ["FRAME","REROUTE", "GROUP"] + node_ignore = ["FRAME", "REROUTE", "GROUP"] # Check if one node is selected at least if not (len(node_selected) > 0): @@ -3859,9 +3923,11 @@ class NWMergeNodesMenu(Menu, NWBase): props.mode = 'MIX' props.merge_type = 'ALPHAOVER' + class NWMergeGeometryMenu(Menu, NWBase): bl_idname = "NODE_MT_nw_merge_geometry_menu" bl_label = "Merge Selected Nodes using Geometry Nodes" + def draw(self, context): layout = self.layout # The boolean node + Join Geometry node @@ -3870,6 +3936,7 @@ class NWMergeGeometryMenu(Menu, NWBase): props.mode = type props.merge_type = 'GEOMETRY' + class NWMergeShadersMenu(Menu, NWBase): bl_idname = "NODE_MT_nw_merge_shaders_menu" bl_label = "Merge Selected Nodes using Shaders" @@ -3906,7 +3973,7 @@ class NWConnectionListOutputs(Menu, NWBase): for index, output in enumerate(n1.outputs): # Only show sockets that are exposed. if output.enabled: - layout.operator(NWCallInputsMenu.bl_idname, text=output.name, icon="RADIOBUT_OFF").from_socket=index + layout.operator(NWCallInputsMenu.bl_idname, text=output.name, icon="RADIOBUT_OFF").from_socket = index class NWConnectionListInputs(Menu, NWBase): @@ -4176,7 +4243,7 @@ def save_viewer_menu_func(self, context): def reset_nodes_button(self, context): node_active = context.active_node node_selected = context.selected_nodes - node_ignore = ["FRAME","REROUTE", "GROUP"] + node_ignore = ["FRAME", "REROUTE", "GROUP"] # Check if active node is in the selection and respective type if (len(node_selected) == 1) and node_active and node_active.select and node_active.type not in node_ignore: @@ -4318,10 +4385,14 @@ kmi_defs = ( (NWLinkActiveToSelected.bl_idname, 'SEMI_COLON', 'PRESS', False, True, False, (('replace', True), ('use_node_name', False), ('use_outputs_names', True),), "Link active to selected (Replace links, output names)"), # CHANGE MIX FACTOR - (NWChangeMixFactor.bl_idname, 'LEFT_ARROW', 'PRESS', False, False, True, (('option', -0.1),), "Reduce Mix Factor by 0.1"), - (NWChangeMixFactor.bl_idname, 'RIGHT_ARROW', 'PRESS', False, False, True, (('option', 0.1),), "Increase Mix Factor by 0.1"), - (NWChangeMixFactor.bl_idname, 'LEFT_ARROW', 'PRESS', False, True, True, (('option', -0.01),), "Reduce Mix Factor by 0.01"), - (NWChangeMixFactor.bl_idname, 'RIGHT_ARROW', 'PRESS', False, True, True, (('option', 0.01),), "Increase Mix Factor by 0.01"), + (NWChangeMixFactor.bl_idname, 'LEFT_ARROW', 'PRESS', False, + False, True, (('option', -0.1),), "Reduce Mix Factor by 0.1"), + (NWChangeMixFactor.bl_idname, 'RIGHT_ARROW', 'PRESS', False, + False, True, (('option', 0.1),), "Increase Mix Factor by 0.1"), + (NWChangeMixFactor.bl_idname, 'LEFT_ARROW', 'PRESS', False, + True, True, (('option', -0.01),), "Reduce Mix Factor by 0.01"), + (NWChangeMixFactor.bl_idname, 'RIGHT_ARROW', 'PRESS', False, + True, True, (('option', 0.01),), "Increase Mix Factor by 0.01"), (NWChangeMixFactor.bl_idname, 'LEFT_ARROW', 'PRESS', True, True, True, (('option', 0.0),), "Set Mix Factor to 0.0"), (NWChangeMixFactor.bl_idname, 'RIGHT_ARROW', 'PRESS', True, True, True, (('option', 1.0),), "Set Mix Factor to 1.0"), (NWChangeMixFactor.bl_idname, 'NUMPAD_0', 'PRESS', True, True, True, (('option', 0.0),), "Set Mix Factor to 0.0"), @@ -4333,16 +4404,19 @@ kmi_defs = ( # MODIFY LABEL (Alt Shift L) (NWModifyLabels.bl_idname, 'L', 'PRESS', False, True, True, None, "Modify node labels"), # Copy Label from active to selected - (NWCopyLabel.bl_idname, 'V', 'PRESS', False, True, False, (('option', 'FROM_ACTIVE'),), "Copy label from active to selected"), + (NWCopyLabel.bl_idname, 'V', 'PRESS', False, True, False, + (('option', 'FROM_ACTIVE'),), "Copy label from active to selected"), # DETACH OUTPUTS (Alt Shift D) (NWDetachOutputs.bl_idname, 'D', 'PRESS', False, True, True, None, "Detach outputs"), # LINK TO OUTPUT NODE (O) (NWLinkToOutputNode.bl_idname, 'O', 'PRESS', False, False, False, None, "Link to output node"), # SELECT PARENT/CHILDREN # Select Children - (NWSelectParentChildren.bl_idname, 'RIGHT_BRACKET', 'PRESS', False, False, False, (('option', 'CHILD'),), "Select children"), + (NWSelectParentChildren.bl_idname, 'RIGHT_BRACKET', 'PRESS', + False, False, False, (('option', 'CHILD'),), "Select children"), # Select Parent - (NWSelectParentChildren.bl_idname, 'LEFT_BRACKET', 'PRESS', False, False, False, (('option', 'PARENT'),), "Select Parent"), + (NWSelectParentChildren.bl_idname, 'LEFT_BRACKET', 'PRESS', + False, False, False, (('option', 'PARENT'),), "Select Parent"), # Add Texture Setup (NWAddTextureSetup.bl_idname, 'T', 'PRESS', True, False, False, None, "Add texture setup"), # Add Principled BSDF Texture Setup @@ -4356,8 +4430,10 @@ kmi_defs = ( # Swap Links (NWSwapLinks.bl_idname, 'S', 'PRESS', False, False, True, None, "Swap Links"), # Preview Node - (NWPreviewNode.bl_idname, 'LEFTMOUSE', 'PRESS', True, True, False, (('run_in_geometry_nodes', False),), "Preview node output"), - (NWPreviewNode.bl_idname, 'LEFTMOUSE', 'PRESS', False, True, True, (('run_in_geometry_nodes', True),), "Preview node output"), + (NWPreviewNode.bl_idname, 'LEFTMOUSE', 'PRESS', True, True, False, + (('run_in_geometry_nodes', False),), "Preview node output"), + (NWPreviewNode.bl_idname, 'LEFTMOUSE', 'PRESS', False, True, + True, (('run_in_geometry_nodes', True),), "Preview node output"), # Reload Images (NWReloadImages.bl_idname, 'R', 'PRESS', False, False, True, None, "Reload images"), # Lazy Mix @@ -4365,18 +4441,22 @@ kmi_defs = ( # Lazy Connect (NWLazyConnect.bl_idname, 'RIGHTMOUSE', 'PRESS', False, False, True, (('with_menu', False),), "Lazy Connect"), # Lazy Connect with Menu - (NWLazyConnect.bl_idname, 'RIGHTMOUSE', 'PRESS', False, True, True, (('with_menu', True),), "Lazy Connect with Socket Menu"), + (NWLazyConnect.bl_idname, 'RIGHTMOUSE', 'PRESS', False, True, + True, (('with_menu', True),), "Lazy Connect with Socket Menu"), # Viewer Tile Center (NWViewerFocus.bl_idname, 'LEFTMOUSE', 'DOUBLE_CLICK', False, False, False, None, "Set Viewers Tile Center"), # Align Nodes (NWAlignNodes.bl_idname, 'EQUAL', 'PRESS', False, True, False, None, "Align selected nodes neatly in a row/column"), # Reset Nodes (Back Space) - (NWResetNodes.bl_idname, 'BACK_SPACE', 'PRESS', False, False, False, None, "Revert node back to default state, but keep connections"), + (NWResetNodes.bl_idname, 'BACK_SPACE', 'PRESS', False, False, False, + None, "Revert node back to default state, but keep connections"), # MENUS ('wm.call_menu', 'W', 'PRESS', False, True, False, (('name', NodeWranglerMenu.bl_idname),), "Node Wrangler menu"), ('wm.call_menu', 'SLASH', 'PRESS', False, False, False, (('name', NWAddReroutesMenu.bl_idname),), "Add Reroutes menu"), - ('wm.call_menu', 'NUMPAD_SLASH', 'PRESS', False, False, False, (('name', NWAddReroutesMenu.bl_idname),), "Add Reroutes menu"), - ('wm.call_menu', 'BACK_SLASH', 'PRESS', False, False, False, (('name', NWLinkActiveToSelectedMenu.bl_idname),), "Link active to selected (menu)"), + ('wm.call_menu', 'NUMPAD_SLASH', 'PRESS', False, False, False, + (('name', NWAddReroutesMenu.bl_idname),), "Add Reroutes menu"), + ('wm.call_menu', 'BACK_SLASH', 'PRESS', False, False, False, + (('name', NWLinkActiveToSelectedMenu.bl_idname),), "Link active to selected (menu)"), ('wm.call_menu', 'C', 'PRESS', False, True, False, (('name', NWCopyToSelectedMenu.bl_idname),), "Copy to selected (menu)"), ('wm.call_menu', 'S', 'PRESS', False, True, False, (('name', NWSwitchNodeTypeMenu.bl_idname),), "Switch node type menu"), ) @@ -4440,6 +4520,7 @@ classes = ( NWSwitchNodeTypeMenu, ) + def register(): from bpy.utils import register_class @@ -4541,5 +4622,6 @@ def unregister(): for cls in classes: unregister_class(cls) + if __name__ == "__main__": register() -- 2.30.2