diff options
Diffstat (limited to 'node_wrangler.py')
-rw-r--r-- | node_wrangler.py | 269 |
1 files changed, 145 insertions, 124 deletions
diff --git a/node_wrangler.py b/node_wrangler.py index b535a580..d3fd8448 100644 --- a/node_wrangler.py +++ b/node_wrangler.py @@ -20,7 +20,7 @@ bl_info = { "name": "Node Wrangler", "author": "Bartek Skorupa, Greg Zaal, Sebastian Koenig, Christian Brinkmann, Florian Meyer", "version": (3, 35), - "blender": (2, 78, 0), + "blender": (2, 80, 0), "location": "Node Editor Toolbar or Ctrl-Space", "description": "Various tools to enhance and speed up node-based workflow", "warning": "", @@ -115,7 +115,7 @@ shaders_input_nodes_props = ( # Keeping mixed case to avoid having to translate entries when adding new nodes in operators. shaders_output_nodes_props = ( ('ShaderNodeOutputMaterial', 'OUTPUT_MATERIAL', 'Material Output'), - ('ShaderNodeOutputLamp', 'OUTPUT_LAMP', 'Lamp Output'), + ('ShaderNodeOutputLight', 'OUTPUT_LIGHT', 'Light Output'), ('ShaderNodeOutputWorld', 'OUTPUT_WORLD', 'World Output'), ) # (rna_type.identifier, type, rna_type.name) @@ -332,7 +332,7 @@ compo_layout_nodes_props = ( blender_mat_input_nodes_props = ( ('ShaderNodeMaterial', 'MATERIAL', 'Material'), ('ShaderNodeCameraData', 'CAMERA', 'Camera Data'), - ('ShaderNodeLampData', 'LAMP', 'Lamp Data'), + ('ShaderNodeLightData', 'LIGHT', 'Light Data'), ('ShaderNodeValue', 'VALUE', 'Value'), ('ShaderNodeRGB', 'RGB', 'RGB'), ('ShaderNodeTexture', 'TEXTURE', 'Texture'), @@ -547,13 +547,16 @@ draw_color_sets = { } +def is_cycles_or_eevee(context): + return context.scene.render.engine in {'CYCLES', 'BLENDER_EEVEE'} + + def nice_hotkey_name(punc): # convert the ugly string name into the actual character pairs = ( ('LEFTMOUSE', "LMB"), ('MIDDLEMOUSE', "MMB"), ('RIGHTMOUSE', "RMB"), - ('SELECTMOUSE', "Select"), ('WHEELUPMOUSE', "Wheel Up"), ('WHEELDOWNMOUSE', "Wheel Down"), ('WHEELINMOUSE', "Wheel In"), @@ -1000,39 +1003,39 @@ def get_nodes_links(context): # Principled prefs class NWPrincipledPreferences(bpy.types.PropertyGroup): - base_color = StringProperty( + base_color: StringProperty( name='Base Color', default='diffuse diff albedo base col color', description='Naming Components for Base Color maps') - sss_color = StringProperty( + sss_color: StringProperty( name='Subsurface Color', default='sss subsurface', description='Naming Components for Subsurface Color maps') - metallic = StringProperty( + metallic: StringProperty( name='Metallic', default='metallic metalness metal mtl', description='Naming Components for metallness maps') - specular = StringProperty( + specular: StringProperty( name='Specular', default='specularity specular spec spc', description='Naming Components for Specular maps') - normal = StringProperty( + normal: StringProperty( name='Normal', default='normal nor nrm nrml norm', description='Naming Components for Normal maps') - bump = StringProperty( + bump: StringProperty( name='Bump', default='bump bmp', description='Naming Components for bump maps') - rough = StringProperty( + rough: StringProperty( name='Roughness', default='roughness rough rgh', description='Naming Components for roughness maps') - gloss = StringProperty( + gloss: StringProperty( name='Gloss', default='gloss glossy glossyness', description='Naming Components for glossy maps') - displacement = StringProperty( + displacement: StringProperty( name='Displacement', default='displacement displace disp dsp height heightmap', description='Naming Components for displacement maps') @@ -1041,7 +1044,7 @@ class NWPrincipledPreferences(bpy.types.PropertyGroup): class NWNodeWrangler(bpy.types.AddonPreferences): bl_idname = __name__ - merge_hide = EnumProperty( + merge_hide: EnumProperty( name="Hide Mix nodes", items=( ("ALWAYS", "Always", "Always collapse the new merge nodes"), @@ -1050,7 +1053,7 @@ class NWNodeWrangler(bpy.types.AddonPreferences): ), default='NON_SHADER', description="When merging nodes with the Ctrl+Numpad0 hotkey (and similar) specify whether to collapse them or show the full node with options expanded") - merge_position = EnumProperty( + merge_position: EnumProperty( name="Mix Node Position", items=( ("CENTER", "Center", "Place the Mix node between the two nodes"), @@ -1059,22 +1062,22 @@ class NWNodeWrangler(bpy.types.AddonPreferences): default='CENTER', description="When merging nodes with the Ctrl+Numpad0 hotkey (and similar) specify the position of the new nodes") - show_hotkey_list = BoolProperty( + show_hotkey_list: BoolProperty( name="Show Hotkey List", default=False, description="Expand this box into a list of all the hotkeys for functions in this addon" ) - hotkey_list_filter = StringProperty( + hotkey_list_filter: StringProperty( name=" Filter by Name", default="", description="Show only hotkeys that have this text in their name" ) - show_principled_lists = BoolProperty( + show_principled_lists: BoolProperty( name="Show Principled naming tags", default=False, description="Expand this box into a list of all naming tags for principled texture setup" ) - principled_tags = bpy.props.PointerProperty(type=NWPrincipledPreferences) + principled_tags: bpy.props.PointerProperty(type=NWPrincipledPreferences) def draw(self, context): layout = self.layout @@ -1113,7 +1116,7 @@ class NWNodeWrangler(bpy.types.AddonPreferences): if self.hotkey_list_filter.lower() in hotkey_name.lower(): row = col.row(align=True) - row.label(hotkey_name) + row.label(text=hotkey_name) keystr = nice_hotkey_name(hotkey[1]) if hotkey[4]: keystr = "Shift " + keystr @@ -1121,7 +1124,7 @@ class NWNodeWrangler(bpy.types.AddonPreferences): keystr = "Alt " + keystr if hotkey[3]: keystr = "Ctrl " + keystr - row.label(keystr) + row.label(text=keystr) @@ -1223,7 +1226,7 @@ class NWLazyConnect(Operator, NWBase): bl_idname = "node.nw_lazy_connect" bl_label = "Lazy Connect" bl_options = {'REGISTER', 'UNDO'} - with_menu = BoolProperty() + with_menu: BoolProperty() def modal(self, context, event): context.area.tag_redraw() @@ -1329,12 +1332,12 @@ 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_LAMP', \ + 'SPLITVIEWER', 'OUTPUT_FILE', 'LEVELS', 'OUTPUT_LIGHT', \ 'OUTPUT_WORLD', 'GROUP_INPUT', 'GROUP_OUTPUT', 'FRAME'] if node.type in end_types: return False @@ -1558,8 +1561,8 @@ class NWResetBG(Operator, NWBase): def execute(self, context): context.space_data.backdrop_zoom = 1 - context.space_data.backdrop_x = 0 - context.space_data.backdrop_y = 0 + context.space_data.backdrop_offset[0] = 0 + context.space_data.backdrop_offset[1] = 0 return {'FINISHED'} @@ -1567,9 +1570,10 @@ class NWAddAttrNode(Operator, NWBase): """Add an Attribute node with this name""" bl_idname = 'node.nw_add_attr_node' bl_label = 'Add UV map' - attr_name = StringProperty() bl_options = {'REGISTER', 'UNDO'} + attr_name: StringProperty() + def execute(self, context): bpy.ops.node.add_node('INVOKE_DEFAULT', use_transform=True, type="ShaderNodeAttribute") nodes, links = get_nodes_links(context) @@ -1585,7 +1589,7 @@ class NWEmissionViewer(Operator, NWBase): @classmethod def poll(cls, context): - is_cycles = context.scene.render.engine == 'CYCLES' + is_cycles = is_cycles_or_eevee(context) if nw_check(context): space = context.space_data if space.tree_type == 'ShaderNodeTree' and is_cycles: @@ -1600,13 +1604,13 @@ class NWEmissionViewer(Operator, NWBase): space = context.space_data shader_type = space.shader_type if shader_type == 'OBJECT': - if space.id not in [lamp for lamp in bpy.data.lamps]: # cannot use bpy.data.lamps directly as iterable + if space.id not in [light for light in bpy.data.lights]: # cannot use bpy.data.lights directly as iterable shader_output_type = "OUTPUT_MATERIAL" shader_output_ident = "ShaderNodeOutputMaterial" shader_viewer_ident = "ShaderNodeEmission" else: - shader_output_type = "OUTPUT_LAMP" - shader_output_ident = "ShaderNodeOutputLamp" + shader_output_type = "OUTPUT_LIGHT" + shader_output_ident = "ShaderNodeOutputLight" shader_viewer_ident = "ShaderNodeEmission" elif shader_type == 'WORLD': @@ -1734,9 +1738,19 @@ class NWFrameSelected(Operator, NWBase): bl_label = "Frame Selected" bl_description = "Add a frame node and parent the selected nodes to it" bl_options = {'REGISTER', 'UNDO'} - label_prop = StringProperty(name='Label', default=' ', description='The visual name of the frame node') - color_prop = FloatVectorProperty(name="Color", description="The color of the frame node", default=(0.6, 0.6, 0.6), - min=0, max=1, step=1, precision=3, subtype='COLOR_GAMMA', size=3) + + label_prop: StringProperty( + name='Label', + description='The visual name of the frame node', + default=' ' + ) + color_prop: FloatVectorProperty( + name="Color", + description="The color of the frame node", + default=(0.6, 0.6, 0.6), + min=0, max=1, step=1, precision=3, + subtype='COLOR_GAMMA', size=3 + ) def execute(self, context): nodes, links = get_nodes_links(context) @@ -1795,7 +1809,7 @@ class NWSwitchNodeType(Operator, NWBase): bl_label = "Switch Node Type" bl_options = {'REGISTER', 'UNDO'} - to_type = EnumProperty( + to_type: EnumProperty( name="Switch to type", items=list(shaders_input_nodes_props) + list(shaders_output_nodes_props) + @@ -2009,12 +2023,12 @@ class NWMergeNodes(Operator, NWBase): bl_description = "Merge Selected Nodes" bl_options = {'REGISTER', 'UNDO'} - mode = EnumProperty( + mode: EnumProperty( name="mode", description="All possible blend types and math operations", items=blend_types + [op for op in operations if op not in blend_types], ) - merge_type = EnumProperty( + merge_type: EnumProperty( name="merge type", description="Type of Merge to be used", items=( @@ -2260,11 +2274,11 @@ class NWBatchChangeNodes(Operator, NWBase): bl_description = "Batch Change Blend Type and Math Operation" bl_options = {'REGISTER', 'UNDO'} - blend_type = EnumProperty( + blend_type: EnumProperty( name="Blend Type", items=blend_types + navs, ) - operation = EnumProperty( + operation: EnumProperty( name="Operation", items=operations + navs, ) @@ -2326,7 +2340,7 @@ class NWChangeMixFactor(Operator, NWBase): # option: Change factor. # If option is 1.0 or 0.0 - set to 1.0 or 0.0 # Else - change factor by option value. - option = FloatProperty() + option: FloatProperty() def execute(self, context): nodes, links = get_nodes_links(context) @@ -2465,7 +2479,7 @@ class NWCopyLabel(Operator, NWBase): bl_label = "Copy Label" bl_options = {'REGISTER', 'UNDO'} - option = EnumProperty( + option: EnumProperty( name="option", description="Source of name of label", items=( @@ -2509,7 +2523,7 @@ class NWClearLabel(Operator, NWBase): bl_label = "Clear Label" bl_options = {'REGISTER', 'UNDO'} - option = BoolProperty() + option: BoolProperty() def execute(self, context): nodes, links = get_nodes_links(context) @@ -2531,16 +2545,16 @@ class NWModifyLabels(Operator, NWBase): bl_label = "Modify Labels" bl_options = {'REGISTER', 'UNDO'} - prepend = StringProperty( + prepend: StringProperty( name="Add to Beginning" ) - append = StringProperty( + append: StringProperty( name="Add to End" ) - replace_from = StringProperty( + replace_from: StringProperty( name="Text to Replace" ) - replace_to = StringProperty( + replace_to: StringProperty( name="Replace with" ) @@ -2564,14 +2578,14 @@ 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): valid = False if nw_check(context): space = context.space_data - if space.tree_type == 'ShaderNodeTree' and context.scene.render.engine == 'CYCLES': + if space.tree_type == 'ShaderNodeTree' and is_cycles_or_eevee(context): valid = True return valid @@ -2642,26 +2656,28 @@ class NWAddPrincipledSetup(Operator, NWBase, ImportHelper): bl_description = "Add Texture Node Setup for Principled BSDF" bl_options = {'REGISTER', 'UNDO'} - directory = StringProperty( - name='Directory', - subtype='DIR_PATH', - default='', - description='Folder to search in for image files') - files = CollectionProperty( - type=bpy.types.OperatorFileListElement, - options={'HIDDEN', 'SKIP_SAVE'}) + directory: StringProperty( + name='Directory', + subtype='DIR_PATH', + default='', + description='Folder to search in for image files' + ) + files: CollectionProperty( + type=bpy.types.OperatorFileListElement, + options={'HIDDEN', 'SKIP_SAVE'} + ) order = [ "filepath", "files", - ] + ] @classmethod def poll(cls, context): valid = False if nw_check(context): space = context.space_data - if space.tree_type == 'ShaderNodeTree' and context.scene.render.engine == 'CYCLES': + if space.tree_type == 'ShaderNodeTree' and is_cycles_or_eevee(context): valid = True return valid @@ -2755,35 +2771,18 @@ class NWAddPrincipledSetup(Operator, NWBase, ImportHelper): disp_texture.color_space = 'NONE' # Add displacement offset nodes - math_sub = nodes.new(type='ShaderNodeMath') - math_sub.operation = 'SUBTRACT' - math_sub.label = 'Offset' - math_sub.location = active_node.location + Vector((0, -560)) - math_mul = nodes.new(type='ShaderNodeMath') - math_mul.operation = 'MULTIPLY' - math_mul.label = 'Strength' - math_mul.location = math_sub.location + Vector((200, 0)) - link = links.new(math_mul.inputs[0], math_sub.outputs[0]) - link = links.new(math_sub.inputs[0], disp_texture.outputs[0]) - - # Turn on true displacement in the material + disp_node = nodes.new(type='ShaderNodeDisplacement') + disp_node.location = active_node.location + Vector((0, -560)) + link = links.new(disp_node.inputs[0], disp_texture.outputs[0]) + + # TODO Turn on true displacement in the material # Too complicated for now - ''' - # Frame. Does not update immediately - # Seems to need an editor redraw - frame = nodes.new(type='NodeFrame') - frame.label = 'Displacement' - math_sub.parent = frame - math_mul.parent = frame - frame.update() - ''' - - #find output node + # Find output node output_node = [n for n in nodes if n.bl_idname == 'ShaderNodeOutputMaterial'] if output_node: if not output_node[0].inputs[2].is_linked: - link = links.new(output_node[0].inputs[2], math_mul.outputs[0]) + link = links.new(output_node[0].inputs[2], disp_node.outputs[0]) continue @@ -2850,23 +2849,24 @@ class NWAddPrincipledSetup(Operator, NWBase, ImportHelper): # Alignment for i, texture_node in enumerate(texture_nodes): - offset = Vector((-400, (i * -260) + 200)) + offset = Vector((-550, (i * -280) + 200)) texture_node.location = active_node.location + offset if normal_node: # Extra alignment if normal node was added - normal_node.location = normal_node_texture.location + Vector((200, 0)) + normal_node.location = normal_node_texture.location + Vector((300, 0)) if roughness_node: # Alignment of invert node if glossy map - invert_node.location = roughness_node.location + Vector((200, 0)) + invert_node.location = roughness_node.location + Vector((300, 0)) # Add texture input + mapping mapping = nodes.new(type='ShaderNodeMapping') - mapping.location = active_node.location + Vector((-900, 0)) + mapping.location = active_node.location + Vector((-1050, 0)) if len(texture_nodes) > 1: # 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))) reroute.location = tex_coords + Vector((-50, -120)) for texture_node in texture_nodes: @@ -2880,6 +2880,20 @@ class NWAddPrincipledSetup(Operator, NWBase, ImportHelper): texture_input.location = mapping.location + Vector((-200, 0)) link = links.new(mapping.inputs[0], texture_input.outputs[2]) + # Create frame around tex coords and mapping + frame = nodes.new(type='NodeFrame') + frame.label = 'Mapping' + mapping.parent = frame + texture_input.parent = frame + frame.update() + + # Create frame around texture nodes + frame = nodes.new(type='NodeFrame') + frame.label = 'Textures' + for tnode in texture_nodes: + tnode.parent = frame + frame.update() + # Just to be sure active_node.select = False nodes.update() @@ -2895,7 +2909,7 @@ class NWAddReroutes(Operator, NWBase): bl_description = "Add Reroutes to Outputs" bl_options = {'REGISTER', 'UNDO'} - option = EnumProperty( + option: EnumProperty( name="option", items=[ ('ALL', 'to all', 'Add to all outputs'), @@ -2995,9 +3009,9 @@ class NWLinkActiveToSelected(Operator, NWBase): bl_label = "Link Active Node to Selected" bl_options = {'REGISTER', 'UNDO'} - replace = BoolProperty() - use_node_name = BoolProperty() - use_outputs_names = BoolProperty() + replace: BoolProperty() + use_node_name: BoolProperty() + use_outputs_names: BoolProperty() @classmethod def poll(cls, context): @@ -3075,7 +3089,7 @@ class NWAlignNodes(Operator, NWBase): bl_idname = "node.nw_align_nodes" bl_label = "Align Nodes" bl_options = {'REGISTER', 'UNDO'} - margin = IntProperty(name='Margin', default=50, description='The amount of space between nodes') + margin: IntProperty(name='Margin', default=50, description='The amount of space between nodes') def execute(self, context): nodes, links = get_nodes_links(context) @@ -3145,7 +3159,7 @@ class NWSelectParentChildren(Operator, NWBase): bl_label = "Select Parent or Children" bl_options = {'REGISTER', 'UNDO'} - option = EnumProperty( + option: EnumProperty( name="option", items=( ('PARENT', 'Select Parent', 'Select Parent Frame'), @@ -3228,7 +3242,7 @@ class NWLinkToOutputNode(Operator, NWBase): if not output_node: bpy.ops.node.select_all(action="DESELECT") if tree_type == 'ShaderNodeTree': - if context.scene.render.engine == 'CYCLES': + if is_cycles_or_eevee(context): output_node = nodes.new('ShaderNodeOutputMaterial') else: output_node = nodes.new('ShaderNodeOutput') @@ -3249,7 +3263,7 @@ class NWLinkToOutputNode(Operator, NWBase): break out_input_index = 0 - if tree_type == 'ShaderNodeTree' and context.scene.render.engine == 'CYCLES': + if tree_type == 'ShaderNodeTree' and is_cycles_or_eevee(context): if active.outputs[output_index].name == 'Volume': out_input_index = 1 elif active.outputs[output_index].type != 'SHADER': # connect to displacement if not a shader @@ -3266,8 +3280,8 @@ class NWMakeLink(Operator, NWBase): bl_idname = 'node.nw_make_link' bl_label = 'Make Link' bl_options = {'REGISTER', 'UNDO'} - from_socket = IntProperty() - to_socket = IntProperty() + from_socket: IntProperty() + to_socket: IntProperty() def execute(self, context): nodes, links = get_nodes_links(context) @@ -3287,7 +3301,7 @@ class NWCallInputsMenu(Operator, NWBase): bl_idname = 'node.nw_call_inputs_menu' bl_label = 'Make Link' bl_options = {'REGISTER', 'UNDO'} - from_socket = IntProperty() + from_socket: IntProperty() def execute(self, context): nodes, links = get_nodes_links(context) @@ -3308,9 +3322,17 @@ class NWAddSequence(Operator, ImportHelper): bl_idname = 'node.nw_add_sequence' bl_label = 'Import Image Sequence' bl_options = {'REGISTER', 'UNDO'} - directory = StringProperty(subtype="DIR_PATH") - filename = StringProperty(subtype="FILE_NAME") - files = CollectionProperty(type=bpy.types.OperatorFileListElement, options={'HIDDEN', 'SKIP_SAVE'}) + + directory: StringProperty( + subtype="DIR_PATH" + ) + filename: StringProperty( + subtype="FILE_NAME" + ) + files: CollectionProperty( + type=bpy.types.OperatorFileListElement, + options={'HIDDEN', 'SKIP_SAVE'} + ) def execute(self, context): nodes, links = get_nodes_links(context) @@ -3402,8 +3424,13 @@ class NWAddMultipleImages(Operator, ImportHelper): bl_idname = 'node.nw_add_multiple_images' bl_label = 'Open Selected Images' bl_options = {'REGISTER', 'UNDO'} - directory = StringProperty(subtype="DIR_PATH") - files = CollectionProperty(type=bpy.types.OperatorFileListElement, options={'HIDDEN', 'SKIP_SAVE'}) + directory: StringProperty( + subtype="DIR_PATH" + ) + files: CollectionProperty( + type=bpy.types.OperatorFileListElement, + options={'HIDDEN', 'SKIP_SAVE'} + ) def execute(self, context): nodes, links = get_nodes_links(context) @@ -3450,8 +3477,8 @@ class NWViewerFocus(bpy.types.Operator): bl_idname = "node.nw_viewer_focus" bl_label = "Viewer Focus" - x = bpy.props.IntProperty() - y = bpy.props.IntProperty() + x: bpy.props.IntProperty() + y: bpy.props.IntProperty() @classmethod def poll(cls, context): @@ -3505,8 +3532,8 @@ class NWSaveViewer(bpy.types.Operator, ExportHelper): """Save the current viewer node to an image file""" bl_idname = "node.nw_save_viewer" bl_label = "Save This Image" - filepath = StringProperty(subtype="FILE_PATH") - filename_ext = EnumProperty( + filepath: StringProperty(subtype="FILE_PATH") + filename_ext: EnumProperty( name="Format", description="Choose the file format to save to", items=(('.bmp', "PNG", ""), @@ -3684,7 +3711,7 @@ def drawlayout(context, layout, mode='non-panel'): col.menu(NWSwitchNodeTypeMenu.bl_idname, text="Switch Node Type") col.separator() - if tree_type == 'ShaderNodeTree' and context.scene.render.engine == 'CYCLES': + if tree_type == 'ShaderNodeTree' and is_cycles_or_eevee(context): col = layout.column(align=True) col.operator(NWAddTextureSetup.bl_idname, text="Add Texture Setup", icon='NODE_SEL') col.operator(NWAddPrincipledSetup.bl_idname, text="Add Principled Setup", icon='NODE_SEL') @@ -3725,7 +3752,7 @@ def drawlayout(context, layout, mode='non-panel'): col.separator() col = layout.column(align=True) - col.operator(NWAlignNodes.bl_idname, icon='ALIGN') + col.operator(NWAlignNodes.bl_idname, icon='CENTER_ONLY') col.separator() col = layout.column(align=True) @@ -3737,14 +3764,14 @@ class NodeWranglerPanel(Panel, NWBase): bl_idname = "NODE_PT_nw_node_wrangler" bl_space_type = 'NODE_EDITOR' bl_label = "Node Wrangler" - bl_region_type = "TOOLS" + bl_region_type = "UI" bl_category = "Node Wrangler" - prepend = StringProperty( + prepend: StringProperty( name='prepend', ) - append = StringProperty() - remove = StringProperty() + append: StringProperty() + remove: StringProperty() def draw(self, context): self.layout.label(text="(Quick access: Ctrl+Space)") @@ -3769,7 +3796,7 @@ class NWMergeNodesMenu(Menu, NWBase): def draw(self, context): type = context.space_data.tree_type layout = self.layout - if type == 'ShaderNodeTree' and context.scene.render.engine == 'CYCLES': + if type == 'ShaderNodeTree' and is_cycles_or_eevee(context): layout.menu(NWMergeShadersMenu.bl_idname, text="Use Shaders") layout.menu(NWMergeMixMenu.bl_idname, text="Use Mix Nodes") layout.menu(NWMergeMathMenu.bl_idname, text="Use Math Nodes") @@ -3993,7 +4020,7 @@ class NWVertColMenu(bpy.types.Menu): valid = False if nw_check(context): snode = context.space_data - valid = snode.tree_type == 'ShaderNodeTree' and context.scene.render.engine == 'CYCLES' + valid = snode.tree_type == 'ShaderNodeTree' and is_cycles_or_eevee(context) return valid def draw(self, context): @@ -4028,7 +4055,7 @@ class NWSwitchNodeTypeMenu(Menu, NWBase): layout = self.layout tree = context.space_data.node_tree if tree.type == 'SHADER': - if context.scene.render.engine == 'CYCLES': + if is_cycles_or_eevee(context): layout.menu(NWSwitchShadersInputSubmenu.bl_idname) layout.menu(NWSwitchShadersOutputSubmenu.bl_idname) layout.menu(NWSwitchShadersShaderSubmenu.bl_idname) @@ -4037,7 +4064,7 @@ class NWSwitchNodeTypeMenu(Menu, NWBase): layout.menu(NWSwitchShadersVectorSubmenu.bl_idname) layout.menu(NWSwitchShadersConverterSubmenu.bl_idname) layout.menu(NWSwitchShadersLayoutSubmenu.bl_idname) - if context.scene.render.engine != 'CYCLES': + else: layout.menu(NWSwitchMatInputSubmenu.bl_idname) layout.menu(NWSwitchMatOutputSubmenu.bl_idname) layout.menu(NWSwitchMatColorSubmenu.bl_idname) @@ -4645,7 +4672,7 @@ kmi_defs = ( # Reset Nodes (Back Space) (NWResetNodes.bl_idname, 'BACK_SPACE', 'PRESS', False, False, False, None, "Revert node back to default state, but keep connections"), # MENUS - ('wm.call_menu', 'SPACE', 'PRESS', True, False, False, (('name', NodeWranglerMenu.bl_idname),), "Node Wranger menu"), + ('wm.call_menu', 'SPACE', 'PRESS', True, True, False, (('name', NodeWranglerMenu.bl_idname),), "Node Wranger 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)"), @@ -4781,13 +4808,10 @@ def register(): # menu items bpy.types.NODE_MT_select.append(select_parent_children_buttons) bpy.types.NODE_MT_category_SH_NEW_INPUT.prepend(attr_nodes_menu_func) - bpy.types.NODE_PT_category_SH_NEW_INPUT.prepend(attr_nodes_menu_func) bpy.types.NODE_PT_backdrop.append(bgreset_menu_func) bpy.types.NODE_PT_active_node_generic.append(save_viewer_menu_func) bpy.types.NODE_MT_category_SH_NEW_TEXTURE.prepend(multipleimages_menu_func) - bpy.types.NODE_PT_category_SH_NEW_TEXTURE.prepend(multipleimages_menu_func) bpy.types.NODE_MT_category_CMP_INPUT.prepend(multipleimages_menu_func) - bpy.types.NODE_PT_category_CMP_INPUT.prepend(multipleimages_menu_func) bpy.types.NODE_PT_active_node_generic.prepend(reset_nodes_button) bpy.types.NODE_MT_node.prepend(reset_nodes_button) @@ -4809,13 +4833,10 @@ def unregister(): # menuitems bpy.types.NODE_MT_select.remove(select_parent_children_buttons) bpy.types.NODE_MT_category_SH_NEW_INPUT.remove(attr_nodes_menu_func) - bpy.types.NODE_PT_category_SH_NEW_INPUT.remove(attr_nodes_menu_func) bpy.types.NODE_PT_backdrop.remove(bgreset_menu_func) bpy.types.NODE_PT_active_node_generic.remove(save_viewer_menu_func) bpy.types.NODE_MT_category_SH_NEW_TEXTURE.remove(multipleimages_menu_func) - bpy.types.NODE_PT_category_SH_NEW_TEXTURE.remove(multipleimages_menu_func) bpy.types.NODE_MT_category_CMP_INPUT.remove(multipleimages_menu_func) - bpy.types.NODE_PT_category_CMP_INPUT.remove(multipleimages_menu_func) bpy.types.NODE_PT_active_node_generic.remove(reset_nodes_button) bpy.types.NODE_MT_node.remove(reset_nodes_button) |