Skip to content
Snippets Groups Projects
node_wrangler.py 170 KiB
Newer Older
  • Learn to ignore specific revisions
  •             node_type = "CompositorNodeImage"
            else:
                self.report({'ERROR'}, "Unsupported Node Tree type!")
                return {'CANCELLED'}
    
            new_nodes = []
            for f in self.files:
                fname = f.name
    
                node = nodes.new(node_type)
                new_nodes.append(node)
                node.label = fname
                node.hide = True
                node.width_hidden = 100
                node.location.x = xloc
                node.location.y = yloc
                yloc -= 40
    
                img = bpy.data.images.load(self.directory+fname)
                node.image = img
    
            # shift new nodes up to center of tree
            list_size = new_nodes[0].location.y - new_nodes[-1].location.y
            for node in new_nodes:
                node.select = True
                node.location.y += (list_size/2)
            return {'FINISHED'}
    
    
    
    class NWViewerFocus(bpy.types.Operator):
        """Set the viewer tile center to the mouse position"""
        bl_idname = "node.nw_viewer_focus"
        bl_label = "Viewer Focus"
    
        x = bpy.props.IntProperty()
        y = bpy.props.IntProperty()
    
        @classmethod
        def poll(cls, context):
            return nw_check(context) and context.space_data.tree_type == 'CompositorNodeTree'
    
        def execute(self, context):
            return {'FINISHED'}
    
        def invoke(self, context, event):
            render = context.scene.render
            space = context.space_data
            percent = render.resolution_percentage*0.01
    
    
            nodes, links = get_nodes_links(context)
            viewers = [n for n in nodes if n.type == 'VIEWER']
    
            if viewers:
                mlocx = event.mouse_region_x
                mlocy = event.mouse_region_y
                select_node = bpy.ops.node.select(mouse_x=mlocx, mouse_y=mlocy, extend=False)
    
                if not 'FINISHED' 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_y = context.region.height / 2
    
                    bd_x = render.resolution_x * percent * space.backdrop_zoom
                    bd_y = render.resolution_y * percent * space.backdrop_zoom
    
                    backdrop_center_x = (bd_x / 2) - space.backdrop_x
                    backdrop_center_y = (bd_y / 2) - space.backdrop_y
    
                    margin_x = region_center_x - backdrop_center_x
                    margin_y = region_center_y - backdrop_center_y
    
                    abs_mouse_x = (mlocx - margin_x) / bd_x
                    abs_mouse_y = (mlocy - margin_y) / bd_y
                    
                    for node in viewers:
                        node.center_x = abs_mouse_x
                        node.center_y = abs_mouse_y
                else:
                    return {'PASS_THROUGH'}
    
    def drawlayout(context, layout, mode='non-panel'):
        tree_type = context.space_data.tree_type
    
        col = layout.column(align=True)
        col.menu(NWMergeNodesMenu.bl_idname)
        col.separator()
    
        col = layout.column(align=True)
        col.menu(NWSwitchNodeTypeMenu.bl_idname, text="Switch Node Type")
        col.separator()
    
    
        if tree_type == 'ShaderNodeTree' and context.scene.render.engine == 'CYCLES':
    
            col = layout.column(align=True)
            col.operator(NWAddTextureSetup.bl_idname, text="Add Texture Setup", icon='NODE_SEL')
            col.separator()
    
        col = layout.column(align=True)
        col.operator(NWDetachOutputs.bl_idname, icon='UNLINKED')
    
        col.operator(NWSwapLinks.bl_idname)
    
        col.menu(NWAddReroutesMenu.bl_idname, text="Add Reroutes", icon='LAYER_USED')
        col.separator()
    
        col = layout.column(align=True)
        col.menu(NWLinkActiveToSelectedMenu.bl_idname, text="Link Active To Selected", icon='LINKED')
        col.operator(NWLinkToOutputNode.bl_idname, icon='DRIVER')
        col.separator()
    
        col = layout.column(align=True)
        if mode == 'panel':
            row = col.row(align=True)
            row.operator(NWClearLabel.bl_idname).option = True
            row.operator(NWModifyLabels.bl_idname)
        else:
            col.operator(NWClearLabel.bl_idname).option = True
            col.operator(NWModifyLabels.bl_idname)
        col.menu(NWBatchChangeNodesMenu.bl_idname, text="Batch Change")
        col.separator()
        col.menu(NWCopyToSelectedMenu.bl_idname, text="Copy to Selected")
        col.separator()
    
        col = layout.column(align=True)
        if tree_type == 'CompositorNodeTree':
            col.operator(NWResetBG.bl_idname, icon='ZOOM_PREVIOUS')
        col.operator(NWReloadImages.bl_idname, icon='FILE_REFRESH')
        col.separator()
    
        col = layout.column(align=True)
        col.operator(NWFrameSelected.bl_idname, icon='STICKY_UVS_LOC')
        col.separator()
    
    
        col = layout.column(align=True)
        col.operator(NWAlignNodes.bl_idname, icon='ALIGN')
        col.separator()
    
    
        col = layout.column(align=True)
        col.operator(NWDeleteUnused.bl_idname, icon='CANCEL')
        col.separator()
    
    
    class NodeWranglerPanel(Panel, NWBase):
        bl_idname = "NODE_PT_nw_node_wrangler"
    
        bl_space_type = 'NODE_EDITOR'
    
        bl_region_type = "TOOLS"
        bl_category = "Node Wrangler"
    
    
        prepend = StringProperty(
            name='prepend',
        )
        append = StringProperty()
        remove = StringProperty()
    
    
        def draw(self, context):
    
            self.layout.label(text="(Quick access: Ctrl+Space)")
            drawlayout(context, self.layout, mode='panel')
    
    #
    #  M E N U S
    #
    class NodeWranglerMenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_node_wrangler_menu"
        bl_label = "Node Wrangler"
    
    
        def draw(self, context):
    
            drawlayout(context, self.layout)
    
    
    class NWMergeNodesMenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_merge_nodes_menu"
    
        bl_label = "Merge Selected Nodes"
    
        def draw(self, context):
            type = context.space_data.tree_type
            layout = self.layout
    
            if type == 'ShaderNodeTree' and context.scene.render.engine == 'CYCLES':
    
                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")
    
            props = layout.operator(NWMergeNodes.bl_idname, text="Use Z-Combine Nodes")
            props.mode = 'MIX'
            props.merge_type = 'ZCOMBINE'
    
            props = layout.operator(NWMergeNodes.bl_idname, text="Use Alpha Over Nodes")
            props.mode = 'MIX'
            props.merge_type = 'ALPHAOVER'
    
    class NWMergeShadersMenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_merge_shaders_menu"
    
        bl_label = "Merge Selected Nodes using Shaders"
    
        def draw(self, context):
            layout = self.layout
    
            for type in ('MIX', 'ADD'):
                props = layout.operator(NWMergeNodes.bl_idname, text=type)
    
                props.mode = type
                props.merge_type = 'SHADER'
    
    
    
    class NWMergeMixMenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_merge_mix_menu"
    
        bl_label = "Merge Selected Nodes using Mix"
    
        def draw(self, context):
            layout = self.layout
            for type, name, description in blend_types:
    
                props = layout.operator(NWMergeNodes.bl_idname, text=name)
    
                props.mode = type
                props.merge_type = 'MIX'
    
    
    
    class NWConnectionListOutputs(Menu, NWBase):
        bl_idname = "NODE_MT_nw_connection_list_out"
        bl_label = "From:"
    
        def draw(self, context):
            layout = self.layout
            nodes, links = get_nodes_links(context)
    
            n1 = nodes[context.scene.NWLazySource]
    
            if n1.type == "R_LAYERS":
                index=0
                for o in n1.outputs:
                    if o.enabled:  # Check which passes the render layer has enabled
                        layout.operator(NWCallInputsMenu.bl_idname, text=o.name, icon="RADIOBUT_OFF").from_socket=index
                    index+=1
            else:
                index=0
                for o in n1.outputs:
                    layout.operator(NWCallInputsMenu.bl_idname, text=o.name, icon="RADIOBUT_OFF").from_socket=index
                    index+=1
    
    
    class NWConnectionListInputs(Menu, NWBase):
        bl_idname = "NODE_MT_nw_connection_list_in"
        bl_label = "To:"
    
        def draw(self, context):
            layout = self.layout
            nodes, links = get_nodes_links(context)
    
            n2 = nodes[context.scene.NWLazyTarget]
    
            index = 0
            for i in n2.inputs:
                op = layout.operator(NWMakeLink.bl_idname, text=i.name, icon="FORWARD")
                op.from_socket = context.scene.NWSourceSocket
                op.to_socket = index
                index+=1
    
    
    
    class NWMergeMathMenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_merge_math_menu"
    
        bl_label = "Merge Selected Nodes using Math"
    
        def draw(self, context):
            layout = self.layout
            for type, name, description in operations:
    
                props = layout.operator(NWMergeNodes.bl_idname, text=name)
    
                props.mode = type
                props.merge_type = 'MATH'
    
    
    
    class NWBatchChangeNodesMenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_batch_change_nodes_menu"
    
        bl_label = "Batch Change Selected Nodes"
    
        def draw(self, context):
            layout = self.layout
    
            layout.menu(NWBatchChangeBlendTypeMenu.bl_idname)
            layout.menu(NWBatchChangeOperationMenu.bl_idname)
    
    class NWBatchChangeBlendTypeMenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_batch_change_blend_type_menu"
    
        bl_label = "Batch Change Blend Type"
    
        def draw(self, context):
            layout = self.layout
            for type, name, description in blend_types:
    
                props = layout.operator(NWBatchChangeNodes.bl_idname, text=name)
    
                props.blend_type = type
                props.operation = 'CURRENT'
    
    
    
    class NWBatchChangeOperationMenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_batch_change_operation_menu"
    
        bl_label = "Batch Change Math Operation"
    
        def draw(self, context):
            layout = self.layout
            for type, name, description in operations:
    
                props = layout.operator(NWBatchChangeNodes.bl_idname, text=name)
    
                props.blend_type = 'CURRENT'
                props.operation = type
    
    
    
    class NWCopyToSelectedMenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_copy_node_properties_menu"
    
        bl_label = "Copy to Selected"
    
        def draw(self, context):
            layout = self.layout
    
            layout.operator(NWCopySettings.bl_idname, text="Settings from Active")
            layout.menu(NWCopyLabelMenu.bl_idname)
    
    class NWCopyLabelMenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_copy_label_menu"
    
        bl_label = "Copy Label"
    
        def draw(self, context):
            layout = self.layout
    
            layout.operator(NWCopyLabel.bl_idname, text="from Active Node's Label").option = 'FROM_ACTIVE'
            layout.operator(NWCopyLabel.bl_idname, text="from Linked Node's Label").option = 'FROM_NODE'
            layout.operator(NWCopyLabel.bl_idname, text="from Linked Output's Name").option = 'FROM_SOCKET'
    
    class NWAddReroutesMenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_add_reroutes_menu"
    
        bl_label = "Add Reroutes"
        bl_description = "Add Reroute Nodes to Selected Nodes' Outputs"
    
        def draw(self, context):
            layout = self.layout
    
            layout.operator(NWAddReroutes.bl_idname, text="to All Outputs").option = 'ALL'
            layout.operator(NWAddReroutes.bl_idname, text="to Loose Outputs").option = 'LOOSE'
            layout.operator(NWAddReroutes.bl_idname, text="to Linked Outputs").option = 'LINKED'
    
    class NWLinkActiveToSelectedMenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_link_active_to_selected_menu"
    
        bl_label = "Link Active to Selected"
    
        def draw(self, context):
            layout = self.layout
    
            layout.menu(NWLinkStandardMenu.bl_idname)
            layout.menu(NWLinkUseNodeNameMenu.bl_idname)
            layout.menu(NWLinkUseOutputsNamesMenu.bl_idname)
    
    class NWLinkStandardMenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_link_standard_menu"
    
        bl_label = "To All Selected"
    
        def draw(self, context):
            layout = self.layout
    
            props = layout.operator(NWLinkActiveToSelected.bl_idname, text="Don't Replace Links")
    
            props.replace = False
            props.use_node_name = False
            props.use_outputs_names = False
    
            props = layout.operator(NWLinkActiveToSelected.bl_idname, text="Replace Links")
    
            props.replace = True
            props.use_node_name = False
            props.use_outputs_names = False
    
    
    
    class NWLinkUseNodeNameMenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_link_use_node_name_menu"
    
        bl_label = "Use Node Name/Label"
    
        def draw(self, context):
            layout = self.layout
    
            props = layout.operator(NWLinkActiveToSelected.bl_idname, text="Don't Replace Links")
    
            props.replace = False
            props.use_node_name = True
            props.use_outputs_names = False
    
            props = layout.operator(NWLinkActiveToSelected.bl_idname, text="Replace Links")
    
            props.replace = True
            props.use_node_name = True
            props.use_outputs_names = False
    
    class NWLinkUseOutputsNamesMenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_link_use_outputs_names_menu"
    
        bl_label = "Use Outputs Names"
    
        def draw(self, context):
            layout = self.layout
    
            props = layout.operator(NWLinkActiveToSelected.bl_idname, text="Don't Replace Links")
    
            props.replace = False
            props.use_node_name = False
            props.use_outputs_names = True
    
            props = layout.operator(NWLinkActiveToSelected.bl_idname, text="Replace Links")
    
            props.replace = True
            props.use_node_name = False
            props.use_outputs_names = True
    
    class NWVertColMenu(bpy.types.Menu):
        bl_idname = "NODE_MT_nw_node_vertex_color_menu"
        bl_label = "Vertex Colors"
    
        @classmethod
        def poll(cls, context):
    
            valid = False
            if nw_check(context):
                snode = context.space_data
    
                valid = snode.tree_type == 'ShaderNodeTree' and context.scene.render.engine == 'CYCLES'
    
    
        def draw(self, context):
            l = self.layout
            nodes, links = get_nodes_links(context)
            mat = context.object.active_material
    
            objs = []
            for obj in bpy.data.objects:
                for slot in obj.material_slots:
                    if slot.material == mat:
                        objs.append(obj)
            vcols = []
            for obj in objs:
                if obj.data.vertex_colors:
                    for vcol in obj.data.vertex_colors:
                        vcols.append(vcol.name)
            vcols = list(set(vcols))  # get a unique list
    
            if vcols:
                for vcol in vcols:
                    l.operator(NWAddAttrNode.bl_idname, text=vcol).attr_name = vcol
            else:
                l.label("No Vertex Color layers on objects with this material")
    
    
    class NWSwitchNodeTypeMenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_switch_node_type_menu"
        bl_label = "Switch Type to..."
    
        def draw(self, context):
            layout = self.layout
            tree = context.space_data.node_tree
            if tree.type == 'SHADER':
    
                if context.scene.render.engine == 'CYCLES':
                    layout.menu(NWSwitchShadersInputSubmenu.bl_idname)
                    layout.menu(NWSwitchShadersOutputSubmenu.bl_idname)
                    layout.menu(NWSwitchShadersShaderSubmenu.bl_idname)
                    layout.menu(NWSwitchShadersTextureSubmenu.bl_idname)
                    layout.menu(NWSwitchShadersColorSubmenu.bl_idname)
                    layout.menu(NWSwitchShadersVectorSubmenu.bl_idname)
                    layout.menu(NWSwitchShadersConverterSubmenu.bl_idname)
                    layout.menu(NWSwitchShadersLayoutSubmenu.bl_idname)
                if context.scene.render.engine != 'CYCLES':
                    layout.menu(NWSwitchMatInputSubmenu.bl_idname)
                    layout.menu(NWSwitchMatOutputSubmenu.bl_idname)
                    layout.menu(NWSwitchMatColorSubmenu.bl_idname)
                    layout.menu(NWSwitchMatVectorSubmenu.bl_idname)
                    layout.menu(NWSwitchMatConverterSubmenu.bl_idname)
                    layout.menu(NWSwitchMatLayoutSubmenu.bl_idname)
    
            if tree.type == 'COMPOSITING':
                layout.menu(NWSwitchCompoInputSubmenu.bl_idname)
                layout.menu(NWSwitchCompoOutputSubmenu.bl_idname)
                layout.menu(NWSwitchCompoColorSubmenu.bl_idname)
                layout.menu(NWSwitchCompoConverterSubmenu.bl_idname)
                layout.menu(NWSwitchCompoFilterSubmenu.bl_idname)
                layout.menu(NWSwitchCompoVectorSubmenu.bl_idname)
                layout.menu(NWSwitchCompoMatteSubmenu.bl_idname)
                layout.menu(NWSwitchCompoDistortSubmenu.bl_idname)
                layout.menu(NWSwitchCompoLayoutSubmenu.bl_idname)
    
            if tree.type == 'TEXTURE':
                layout.menu(NWSwitchTexInputSubmenu.bl_idname)
                layout.menu(NWSwitchTexOutputSubmenu.bl_idname)
                layout.menu(NWSwitchTexColorSubmenu.bl_idname)
                layout.menu(NWSwitchTexPatternSubmenu.bl_idname)
                layout.menu(NWSwitchTexTexturesSubmenu.bl_idname)
                layout.menu(NWSwitchTexConverterSubmenu.bl_idname)
                layout.menu(NWSwitchTexDistortSubmenu.bl_idname)
                layout.menu(NWSwitchTexLayoutSubmenu.bl_idname)
    
    
    
    class NWSwitchShadersInputSubmenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_switch_shaders_input_submenu"
        bl_label = "Input"
    
        def draw(self, context):
            layout = self.layout
            for ident, type, rna_name in shaders_input_nodes_props:
                props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name)
                props.to_type = ident
    
    
    class NWSwitchShadersOutputSubmenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_switch_shaders_output_submenu"
        bl_label = "Output"
    
        def draw(self, context):
            layout = self.layout
            for ident, type, rna_name in shaders_output_nodes_props:
                props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name)
                props.to_type = ident
    
    
    class NWSwitchShadersShaderSubmenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_switch_shaders_shader_submenu"
        bl_label = "Shader"
    
        def draw(self, context):
            layout = self.layout
            for ident, type, rna_name in shaders_shader_nodes_props:
                props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name)
                props.to_type = ident
    
    
    class NWSwitchShadersTextureSubmenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_switch_shaders_texture_submenu"
        bl_label = "Texture"
    
        def draw(self, context):
            layout = self.layout
            for ident, type, rna_name in shaders_texture_nodes_props:
                props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name)
                props.to_type = ident
    
    
    class NWSwitchShadersColorSubmenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_switch_shaders_color_submenu"
        bl_label = "Color"
    
        def draw(self, context):
            layout = self.layout
            for ident, type, rna_name in shaders_color_nodes_props:
                props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name)
                props.to_type = ident
    
    
    class NWSwitchShadersVectorSubmenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_switch_shaders_vector_submenu"
        bl_label = "Vector"
    
        def draw(self, context):
            layout = self.layout
            for ident, type, rna_name in shaders_vector_nodes_props:
                props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name)
                props.to_type = ident
    
    
    class NWSwitchShadersConverterSubmenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_switch_shaders_converter_submenu"
        bl_label = "Converter"
    
        def draw(self, context):
            layout = self.layout
            for ident, type, rna_name in shaders_converter_nodes_props:
                props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name)
                props.to_type = ident
    
    
    class NWSwitchShadersLayoutSubmenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_switch_shaders_layout_submenu"
        bl_label = "Layout"
    
        def draw(self, context):
            layout = self.layout
            for ident, type, rna_name in shaders_layout_nodes_props:
                if type != 'FRAME':
                    props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name)
                    props.to_type = ident
    
    
    class NWSwitchCompoInputSubmenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_switch_compo_input_submenu"
        bl_label = "Input"
    
        def draw(self, context):
            layout = self.layout
            for ident, type, rna_name in compo_input_nodes_props:
                props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name)
                props.to_type = ident
    
    
    class NWSwitchCompoOutputSubmenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_switch_compo_output_submenu"
        bl_label = "Output"
    
        def draw(self, context):
            layout = self.layout
            for ident, type, rna_name in compo_output_nodes_props:
                props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name)
                props.to_type = ident
    
    
    class NWSwitchCompoColorSubmenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_switch_compo_color_submenu"
        bl_label = "Color"
    
        def draw(self, context):
            layout = self.layout
            for ident, type, rna_name in compo_color_nodes_props:
                props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name)
                props.to_type = ident
    
    
    class NWSwitchCompoConverterSubmenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_switch_compo_converter_submenu"
        bl_label = "Converter"
    
        def draw(self, context):
            layout = self.layout
            for ident, type, rna_name in compo_converter_nodes_props:
                props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name)
                props.to_type = ident
    
    
    class NWSwitchCompoFilterSubmenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_switch_compo_filter_submenu"
        bl_label = "Filter"
    
        def draw(self, context):
            layout = self.layout
            for ident, type, rna_name in compo_filter_nodes_props:
                props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name)
                props.to_type = ident
    
    
    class NWSwitchCompoVectorSubmenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_switch_compo_vector_submenu"
        bl_label = "Vector"
    
        def draw(self, context):
            layout = self.layout
            for ident, type, rna_name in compo_vector_nodes_props:
                props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name)
                props.to_type = ident
    
    
    class NWSwitchCompoMatteSubmenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_switch_compo_matte_submenu"
        bl_label = "Matte"
    
        def draw(self, context):
            layout = self.layout
            for ident, type, rna_name in compo_matte_nodes_props:
                props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name)
                props.to_type = ident
    
    
    class NWSwitchCompoDistortSubmenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_switch_compo_distort_submenu"
        bl_label = "Distort"
    
        def draw(self, context):
            layout = self.layout
            for ident, type, rna_name in compo_distort_nodes_props:
                props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name)
                props.to_type = ident
    
    
    class NWSwitchCompoLayoutSubmenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_switch_compo_layout_submenu"
        bl_label = "Layout"
    
        def draw(self, context):
            layout = self.layout
            for ident, type, rna_name in compo_layout_nodes_props:
                if type != 'FRAME':
                    props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name)
                    props.to_type = ident
    
    
    
    class NWSwitchMatInputSubmenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_switch_mat_input_submenu"
        bl_label = "Input"
    
        def draw(self, context):
            layout = self.layout
            for ident, type, rna_name in blender_mat_input_nodes_props:
                props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name)
                props.to_type = ident
    
    
    class NWSwitchMatOutputSubmenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_switch_mat_output_submenu"
        bl_label = "Output"
    
        def draw(self, context):
            layout = self.layout
            for ident, type, rna_name in blender_mat_output_nodes_props:
                props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name)
                props.to_type = ident
    
    
    class NWSwitchMatColorSubmenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_switch_mat_color_submenu"
        bl_label = "Color"
    
        def draw(self, context):
            layout = self.layout
            for ident, type, rna_name in blender_mat_color_nodes_props:
                props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name)
                props.to_type = ident
    
    
    class NWSwitchMatVectorSubmenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_switch_mat_vector_submenu"
        bl_label = "Vector"
    
        def draw(self, context):
            layout = self.layout
            for ident, type, rna_name in blender_mat_vector_nodes_props:
                props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name)
                props.to_type = ident
    
    
    class NWSwitchMatConverterSubmenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_switch_mat_converter_submenu"
        bl_label = "Converter"
    
        def draw(self, context):
            layout = self.layout
            for ident, type, rna_name in blender_mat_converter_nodes_props:
                props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name)
                props.to_type = ident
    
    
    class NWSwitchMatLayoutSubmenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_switch_mat_layout_submenu"
        bl_label = "Layout"
    
        def draw(self, context):
            layout = self.layout
            for ident, type, rna_name in blender_mat_layout_nodes_props:
                if type != 'FRAME':
                    props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name)
                    props.to_type = ident
    
    
    class NWSwitchTexInputSubmenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_switch_tex_input_submenu"
        bl_label = "Input"
    
        def draw(self, context):
            layout = self.layout
            for ident, type, rna_name in texture_input_nodes_props:
                props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name)
                props.to_type = ident
    
    
    class NWSwitchTexOutputSubmenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_switch_tex_output_submenu"
        bl_label = "Output"
    
        def draw(self, context):
            layout = self.layout
            for ident, type, rna_name in texture_output_nodes_props:
                props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name)
                props.to_type = ident
    
    
    class NWSwitchTexColorSubmenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_switch_tex_color_submenu"
        bl_label = "Color"
    
        def draw(self, context):
            layout = self.layout
            for ident, type, rna_name in texture_color_nodes_props:
                props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name)
                props.to_type = ident
    
    
    class NWSwitchTexPatternSubmenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_switch_tex_pattern_submenu"
        bl_label = "Pattern"
    
        def draw(self, context):
            layout = self.layout
            for ident, type, rna_name in texture_pattern_nodes_props:
                props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name)
                props.to_type = ident
    
    
    class NWSwitchTexTexturesSubmenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_switch_tex_textures_submenu"
        bl_label = "Textures"
    
        def draw(self, context):
            layout = self.layout
            for ident, type, rna_name in texture_textures_nodes_props:
                props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name)
                props.to_type = ident
    
    
    class NWSwitchTexConverterSubmenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_switch_tex_converter_submenu"
        bl_label = "Converter"
    
        def draw(self, context):
            layout = self.layout
            for ident, type, rna_name in texture_converter_nodes_props:
                props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name)
                props.to_type = ident
    
    
    class NWSwitchTexDistortSubmenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_switch_tex_distort_submenu"
        bl_label = "Distort"
    
        def draw(self, context):
            layout = self.layout
            for ident, type, rna_name in texture_distort_nodes_props:
                props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name)
                props.to_type = ident
    
    
    class NWSwitchTexLayoutSubmenu(Menu, NWBase):
        bl_idname = "NODE_MT_nw_switch_tex_layout_submenu"
        bl_label = "Layout"
    
        def draw(self, context):
            layout = self.layout
            for ident, type, rna_name in texture_layout_nodes_props:
                if type != 'FRAME':
                    props = layout.operator(NWSwitchNodeType.bl_idname, text=rna_name)
                    props.to_type = ident
    
    
    
    
    def select_parent_children_buttons(self, context):
        layout = self.layout
    
        layout.operator(NWSelectParentChildren.bl_idname, text="Select frame's members (children)").option = 'CHILD'
        layout.operator(NWSelectParentChildren.bl_idname, text="Select parent frame").option = 'PARENT'
    
    
    def attr_nodes_menu_func(self, context):
        col = self.layout.column(align=True)
        col.menu("NODE_MT_nw_node_vertex_color_menu")
        col.separator()
    
    
    
    def multipleimages_menu_func(self, context):
        col = self.layout.column(align=True)
        col.operator(NWAddMultipleImages.bl_idname, text="Multiple Images")
        col.operator(NWAddSequence.bl_idname, text="Image Sequence")
        col.separator()
        
    
    
    def bgreset_menu_func(self, context):
        self.layout.operator(NWResetBG.bl_idname)
    
    
    #  REGISTER/UNREGISTER CLASSES AND KEYMAP ITEMS
    
    # kmi_defs entry: (identifier, key, action, CTRL, SHIFT, ALT, props, nice name)
    
    # props entry: (property name, property value)
    kmi_defs = (
        # MERGE NODES
    
        # NWMergeNodes with Ctrl (AUTO).
    
        (NWMergeNodes.bl_idname, 'NUMPAD_0', 'PRESS', True, False, False,
    
            (('mode', 'MIX'), ('merge_type', 'AUTO'),), "Merge Nodes (Automatic)"),
    
        (NWMergeNodes.bl_idname, 'ZERO', 'PRESS', True, False, False,
    
            (('mode', 'MIX'), ('merge_type', 'AUTO'),), "Merge Nodes (Automatic)"),
    
        (NWMergeNodes.bl_idname, 'NUMPAD_PLUS', 'PRESS', True, False, False,
    
            (('mode', 'ADD'), ('merge_type', 'AUTO'),), "Merge Nodes (Add)"),
    
        (NWMergeNodes.bl_idname, 'EQUAL', 'PRESS', True, False, False,
    
            (('mode', 'ADD'), ('merge_type', 'AUTO'),), "Merge Nodes (Add)"),
    
        (NWMergeNodes.bl_idname, 'NUMPAD_ASTERIX', 'PRESS', True, False, False,
    
            (('mode', 'MULTIPLY'), ('merge_type', 'AUTO'),), "Merge Nodes (Multiply)"),
    
        (NWMergeNodes.bl_idname, 'EIGHT', 'PRESS', True, False, False,
    
            (('mode', 'MULTIPLY'), ('merge_type', 'AUTO'),), "Merge Nodes (Multiply)"),
    
        (NWMergeNodes.bl_idname, 'NUMPAD_MINUS', 'PRESS', True, False, False,
    
            (('mode', 'SUBTRACT'), ('merge_type', 'AUTO'),), "Merge Nodes (Subtract)"),
    
        (NWMergeNodes.bl_idname, 'MINUS', 'PRESS', True, False, False,
    
            (('mode', 'SUBTRACT'), ('merge_type', 'AUTO'),), "Merge Nodes (Subtract)"),
    
        (NWMergeNodes.bl_idname, 'NUMPAD_SLASH', 'PRESS', True, False, False,
    
            (('mode', 'DIVIDE'), ('merge_type', 'AUTO'),), "Merge Nodes (Divide)"),
    
        (NWMergeNodes.bl_idname, 'SLASH', 'PRESS', True, False, False,
    
            (('mode', 'DIVIDE'), ('merge_type', 'AUTO'),), "Merge Nodes (Divide)"),
    
        (NWMergeNodes.bl_idname, 'COMMA', 'PRESS', True, False, False,
    
            (('mode', 'LESS_THAN'), ('merge_type', 'MATH'),), "Merge Nodes (Less than)"),
    
        (NWMergeNodes.bl_idname, 'PERIOD', 'PRESS', True, False, False,
    
            (('mode', 'GREATER_THAN'), ('merge_type', 'MATH'),), "Merge Nodes (Greater than)"),
    
        (NWMergeNodes.bl_idname, 'NUMPAD_PERIOD', 'PRESS', True, False, False,
    
            (('mode', 'MIX'), ('merge_type', 'ZCOMBINE'),), "Merge Nodes (Z-Combine)"),
    
        # NWMergeNodes with Ctrl Alt (MIX or ALPHAOVER)
    
        (NWMergeNodes.bl_idname, 'NUMPAD_0', 'PRESS', True, False, True,
    
            (('mode', 'MIX'), ('merge_type', 'ALPHAOVER'),), "Merge Nodes (Alpha Over)"),
    
        (NWMergeNodes.bl_idname, 'ZERO', 'PRESS', True, False, True,
    
            (('mode', 'MIX'), ('merge_type', 'ALPHAOVER'),), "Merge Nodes (Alpha Over)"),
    
        (NWMergeNodes.bl_idname, 'NUMPAD_PLUS', 'PRESS', True, False, True,
    
            (('mode', 'ADD'), ('merge_type', 'MIX'),), "Merge Nodes (Color, Add)"),
    
        (NWMergeNodes.bl_idname, 'EQUAL', 'PRESS', True, False, True,
    
            (('mode', 'ADD'), ('merge_type', 'MIX'),), "Merge Nodes (Color, Add)"),
    
        (NWMergeNodes.bl_idname, 'NUMPAD_ASTERIX', 'PRESS', True, False, True,
    
            (('mode', 'MULTIPLY'), ('merge_type', 'MIX'),), "Merge Nodes (Color, Multiply)"),
    
        (NWMergeNodes.bl_idname, 'EIGHT', 'PRESS', True, False, True,
    
            (('mode', 'MULTIPLY'), ('merge_type', 'MIX'),), "Merge Nodes (Color, Multiply)"),
    
        (NWMergeNodes.bl_idname, 'NUMPAD_MINUS', 'PRESS', True, False, True,
    
            (('mode', 'SUBTRACT'), ('merge_type', 'MIX'),), "Merge Nodes (Color, Subtract)"),
    
        (NWMergeNodes.bl_idname, 'MINUS', 'PRESS', True, False, True,
    
            (('mode', 'SUBTRACT'), ('merge_type', 'MIX'),), "Merge Nodes (Color, Subtract)"),
    
        (NWMergeNodes.bl_idname, 'NUMPAD_SLASH', 'PRESS', True, False, True,
    
            (('mode', 'DIVIDE'), ('merge_type', 'MIX'),), "Merge Nodes (Color, Divide)"),
    
        (NWMergeNodes.bl_idname, 'SLASH', 'PRESS', True, False, True,
    
            (('mode', 'DIVIDE'), ('merge_type', 'MIX'),), "Merge Nodes (Color, Divide)"),
        # NWMergeNodes with Ctrl Shift (MATH)
    
        (NWMergeNodes.bl_idname, 'NUMPAD_PLUS', 'PRESS', True, True, False,
    
            (('mode', 'ADD'), ('merge_type', 'MATH'),), "Merge Nodes (Math, Add)"),
    
        (NWMergeNodes.bl_idname, 'EQUAL', 'PRESS', True, True, False,
    
            (('mode', 'ADD'), ('merge_type', 'MATH'),), "Merge Nodes (Math, Add)"),
    
        (NWMergeNodes.bl_idname, 'NUMPAD_ASTERIX', 'PRESS', True, True, False,
    
            (('mode', 'MULTIPLY'), ('merge_type', 'MATH'),), "Merge Nodes (Math, Multiply)"),
    
        (NWMergeNodes.bl_idname, 'EIGHT', 'PRESS', True, True, False,
    
            (('mode', 'MULTIPLY'), ('merge_type', 'MATH'),), "Merge Nodes (Math, Multiply)"),
    
        (NWMergeNodes.bl_idname, 'NUMPAD_MINUS', 'PRESS', True, True, False,
    
            (('mode', 'SUBTRACT'), ('merge_type', 'MATH'),), "Merge Nodes (Math, Subtract)"),
    
        (NWMergeNodes.bl_idname, 'MINUS', 'PRESS', True, True, False,
    
            (('mode', 'SUBTRACT'), ('merge_type', 'MATH'),), "Merge Nodes (Math, Subtract)"),
    
        (NWMergeNodes.bl_idname, 'NUMPAD_SLASH', 'PRESS', True, True, False,
    
            (('mode', 'DIVIDE'), ('merge_type', 'MATH'),), "Merge Nodes (Math, Divide)"),
    
        (NWMergeNodes.bl_idname, 'SLASH', 'PRESS', True, True, False,
    
            (('mode', 'DIVIDE'), ('merge_type', 'MATH'),), "Merge Nodes (Math, Divide)"),
    
        (NWMergeNodes.bl_idname, 'COMMA', 'PRESS', True, True, False,
    
            (('mode', 'LESS_THAN'), ('merge_type', 'MATH'),), "Merge Nodes (Math, Less than)"),
    
        (NWMergeNodes.bl_idname, 'PERIOD', 'PRESS', True, True, False,
    
            (('mode', 'GREATER_THAN'), ('merge_type', 'MATH'),), "Merge Nodes (Math, Greater than)"),
    
        # BATCH CHANGE NODES
    
        # NWBatchChangeNodes with Alt
    
        (NWBatchChangeNodes.bl_idname, 'NUMPAD_0', 'PRESS', False, False, True,
    
            (('blend_type', 'MIX'), ('operation', 'CURRENT'),), "Batch change blend type (Mix)"),
    
        (NWBatchChangeNodes.bl_idname, 'ZERO', 'PRESS', False, False, True,
    
            (('blend_type', 'MIX'), ('operation', 'CURRENT'),), "Batch change blend type (Mix)"),
    
        (NWBatchChangeNodes.bl_idname, 'NUMPAD_PLUS', 'PRESS', False, False, True,
    
            (('blend_type', 'ADD'), ('operation', 'ADD'),), "Batch change blend type (Add)"),
    
        (NWBatchChangeNodes.bl_idname, 'EQUAL', 'PRESS', False, False, True,
    
            (('blend_type', 'ADD'), ('operation', 'ADD'),), "Batch change blend type (Add)"),
    
        (NWBatchChangeNodes.bl_idname, 'NUMPAD_ASTERIX', 'PRESS', False, False, True,
    
            (('blend_type', 'MULTIPLY'), ('operation', 'MULTIPLY'),), "Batch change blend type (Multiply)"),
    
        (NWBatchChangeNodes.bl_idname, 'EIGHT', 'PRESS', False, False, True,
    
            (('blend_type', 'MULTIPLY'), ('operation', 'MULTIPLY'),), "Batch change blend type (Multiply)"),
    
        (NWBatchChangeNodes.bl_idname, 'NUMPAD_MINUS', 'PRESS', False, False, True,
    
            (('blend_type', 'SUBTRACT'), ('operation', 'SUBTRACT'),), "Batch change blend type (Subtract)"),
    
        (NWBatchChangeNodes.bl_idname, 'MINUS', 'PRESS', False, False, True,
    
            (('blend_type', 'SUBTRACT'), ('operation', 'SUBTRACT'),), "Batch change blend type (Subtract)"),
    
        (NWBatchChangeNodes.bl_idname, 'NUMPAD_SLASH', 'PRESS', False, False, True,
    
            (('blend_type', 'DIVIDE'), ('operation', 'DIVIDE'),), "Batch change blend type (Divide)"),
    
        (NWBatchChangeNodes.bl_idname, 'SLASH', 'PRESS', False, False, True,
    
            (('blend_type', 'DIVIDE'), ('operation', 'DIVIDE'),), "Batch change blend type (Divide)"),
    
        (NWBatchChangeNodes.bl_idname, 'COMMA', 'PRESS', False, False, True,
    
            (('blend_type', 'CURRENT'), ('operation', 'LESS_THAN'),), "Batch change blend type (Current)"),
    
        (NWBatchChangeNodes.bl_idname, 'PERIOD', 'PRESS', False, False, True,
    
            (('blend_type', 'CURRENT'), ('operation', 'GREATER_THAN'),), "Batch change blend type (Current)"),
    
        (NWBatchChangeNodes.bl_idname, 'DOWN_ARROW', 'PRESS', False, False, True,
    
            (('blend_type', 'NEXT'), ('operation', 'NEXT'),), "Batch change blend type (Next)"),
    
        (NWBatchChangeNodes.bl_idname, 'UP_ARROW', 'PRESS', False, False, True,
    
            (('blend_type', 'PREV'), ('operation', 'PREV'),), "Batch change blend type (Previous)"),
    
        # LINK ACTIVE TO SELECTED
    
        # Don't use names, don't replace links (K)
    
        (NWLinkActiveToSelected.bl_idname, 'K', 'PRESS', False, False, False,
    
            (('replace', False), ('use_node_name', False), ('use_outputs_names', False),), "Link active to selected (Don't replace links)"),
    
        # Don't use names, replace links (Shift K)
    
        (NWLinkActiveToSelected.bl_idname, 'K', 'PRESS', False, True, False,
    
            (('replace', True), ('use_node_name', False), ('use_outputs_names', False),), "Link active to selected (Replace links)"),
    
        # Use node name, don't replace links (')
    
        (NWLinkActiveToSelected.bl_idname, 'QUOTE', 'PRESS', False, False, False,
    
            (('replace', False), ('use_node_name', True), ('use_outputs_names', False),), "Link active to selected (Don't replace links, node names)"),
        # Use node name, replace links (Shift ')
    
        (NWLinkActiveToSelected.bl_idname, 'QUOTE', 'PRESS', False, True, False,
    
            (('replace', True), ('use_node_name', True), ('use_outputs_names', False),), "Link active to selected (Replace links, node names)"),
        # Don't use names, don't replace links (;)
    
        (NWLinkActiveToSelected.bl_idname, 'SEMI_COLON', 'PRESS', False, False, False,
    
            (('replace', False), ('use_node_name', False), ('use_outputs_names', True),), "Link active to selected (Don't replace links, output names)"),
    
        # Don't use names, replace links (')
    
        (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', 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"),
        (NWChangeMixFactor.bl_idname, 'ZERO', 'PRESS', True, True, True, (('option', 0.0),), "Set Mix Factor to 0.0"),
        (NWChangeMixFactor.bl_idname, 'NUMPAD_1', 'PRESS', True, True, True, (('option', 1.0),), "Mix Factor to 1.0"),
        (NWChangeMixFactor.bl_idname, 'ONE', 'PRESS', True, True, True, (('option', 1.0),), "Set Mix Factor to 1.0"),
    
        # CLEAR LABEL (Alt L)
    
        (NWClearLabel.bl_idname, 'L', 'PRESS', False, False, True, (('option', False),), "Clear node labels"),
    
        # 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"),
    
    Bartek Skorupa's avatar
    Bartek Skorupa committed
        # DETACH OUTPUTS (Alt Shift D)
    
        (NWDetachOutputs.bl_idname, 'D', 'PRESS', False, True, True, None, "Detach outputs"),
    
    Bartek Skorupa's avatar
    Bartek Skorupa committed
        # LINK TO OUTPUT NODE (O)