From 2d53c4b81b868d5998993de5183abefdbcd46f3c Mon Sep 17 00:00:00 2001 From: Sun Kim Date: Fri, 13 Oct 2023 00:02:00 +0900 Subject: [PATCH] Remove Switch Type operator Remove Switch Type operator as it is no longer operational in all node editors. When the shortcut `Shift + S` is pressed the notice of removal with the future plan of native implementation is displayed. --- node_wrangler/interface.py | 32 +----- node_wrangler/operators.py | 190 ----------------------------------- node_wrangler/preferences.py | 21 ---- 3 files changed, 2 insertions(+), 241 deletions(-) diff --git a/node_wrangler/interface.py b/node_wrangler/interface.py index 05c2c637e..d538528b8 100644 --- a/node_wrangler/interface.py +++ b/node_wrangler/interface.py @@ -20,10 +20,6 @@ def drawlayout(context, layout, mode='non-panel'): 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': col = layout.column(align=True) col.operator(operators.NWAddTextureSetup.bl_idname, text="Add Texture Setup", icon='NODE_SEL') @@ -385,32 +381,8 @@ class NWSwitchNodeTypeMenu(Menu, NWBase): def draw(self, context): layout = self.layout - categories = [c for c in node_categories_iter(context) - if c.name not in ['Group', 'Script']] - for cat in categories: - idname = f"NODE_MT_nw_switch_{cat.identifier}_submenu" - if hasattr(bpy.types, idname): - layout.menu(idname) - else: - layout.label(text="Unable to load altered node lists.") - layout.label(text="Please re-enable Node Wrangler.") - break - - -def draw_switch_category_submenu(self, context): - layout = self.layout - if self.category.name == 'Layout': - for node in self.category.items(context): - if node.nodetype != 'NodeFrame': - props = layout.operator(operators.NWSwitchNodeType.bl_idname, text=node.label) - props.to_type = node.nodetype - else: - for node in self.category.items(context): - if isinstance(node, NodeItemCustom): - node.draw(self, layout, context) - continue - props = layout.operator(operators.NWSwitchNodeType.bl_idname, text=node.label) - props.to_type = node.nodetype + layout.label(text="This operator is removed due to the changes of node menus.", icon='ERROR') + layout.label(text="A native implementation of the function is expected in the future.") # # APPENDAGES TO EXISTING UI diff --git a/node_wrangler/operators.py b/node_wrangler/operators.py index a623861dd..ca05fb695 100644 --- a/node_wrangler/operators.py +++ b/node_wrangler/operators.py @@ -914,195 +914,6 @@ class NWReloadImages(Operator): return {'CANCELLED'} -class NWSwitchNodeType(Operator, NWBase): - """Switch type of selected nodes """ - bl_idname = "node.nw_swtch_node_type" - bl_label = "Switch Node Type" - bl_options = {'REGISTER', 'UNDO'} - - to_type: StringProperty( - name="Switch to type", - default='', - ) - - def execute(self, context): - to_type = self.to_type - if len(to_type) == 0: - return {'CANCELLED'} - - nodes, links = get_nodes_links(context) - # Those types of nodes will not swap. - src_excludes = ('NodeFrame') - # Those attributes of nodes will be copied if possible - attrs_to_pass = ('color', 'hide', 'label', 'mute', 'parent', - 'show_options', 'show_preview', 'show_texture', - 'use_alpha', 'use_clamp', 'use_custom_color', 'location' - ) - selected = [n for n in nodes if n.select] - reselect = [] - for node in [n for n in selected if - n.rna_type.identifier not in src_excludes and - n.rna_type.identifier != to_type]: - new_node = nodes.new(to_type) - for attr in attrs_to_pass: - if hasattr(node, attr) and hasattr(new_node, attr): - setattr(new_node, attr, getattr(node, attr)) - # set image datablock of dst to image of src - if hasattr(node, 'image') and hasattr(new_node, 'image'): - if node.image: - new_node.image = node.image - # Special cases - if new_node.type == 'SWITCH': - new_node.hide = True - # Dictionaries: src_sockets and dst_sockets: - # 'INPUTS': input sockets ordered by type (entry 'MAIN' main type of inputs). - # 'OUTPUTS': output sockets ordered by type (entry 'MAIN' main type of outputs). - # in 'INPUTS' and 'OUTPUTS': - # 'SHADER', 'RGBA', 'VECTOR', 'VALUE' - sockets of those types. - # socket entry: - # (index_in_type, socket_index, socket_name, socket_default_value, socket_links) - src_sockets = { - 'INPUTS': {'SHADER': [], 'RGBA': [], 'VECTOR': [], 'VALUE': [], 'MAIN': None}, - 'OUTPUTS': {'SHADER': [], 'RGBA': [], 'VECTOR': [], 'VALUE': [], 'MAIN': None}, - } - dst_sockets = { - 'INPUTS': {'SHADER': [], 'RGBA': [], 'VECTOR': [], 'VALUE': [], 'MAIN': None}, - 'OUTPUTS': {'SHADER': [], 'RGBA': [], 'VECTOR': [], 'VALUE': [], 'MAIN': None}, - } - types_order_one = 'SHADER', 'RGBA', 'VECTOR', 'VALUE' - types_order_two = 'SHADER', 'VECTOR', 'RGBA', 'VALUE' - # check src node to set src_sockets values and dst node to set dst_sockets dict values - for sockets, nd in ((src_sockets, node), (dst_sockets, new_node)): - # Check node's inputs and outputs and fill proper entries in "sockets" dict - for in_out, in_out_name in ((nd.inputs, 'INPUTS'), (nd.outputs, 'OUTPUTS')): - # enumerate in inputs, then in outputs - # find name, default value and links of socket - for i, socket in enumerate(in_out): - the_name = socket.name - dval = None - # Not every socket, especially in outputs has "default_value" - if hasattr(socket, 'default_value'): - dval = socket.default_value - socket_links = [] - for lnk in socket.links: - socket_links.append(lnk) - # check type of socket to fill proper keys. - 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)) - # 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: - if sockets[in_out_name][type_check]: - sockets[in_out_name]['MAIN'] = type_check - break - - matches = { - 'INPUTS': {'SHADER': [], 'RGBA': [], 'VECTOR': [], 'VALUE_NAME': [], 'VALUE': [], 'MAIN': []}, - 'OUTPUTS': {'SHADER': [], 'RGBA': [], 'VECTOR': [], 'VALUE_NAME': [], 'VALUE': [], 'MAIN': []}, - } - - for inout, soctype in ( - ('INPUTS', 'MAIN',), - ('INPUTS', 'SHADER',), - ('INPUTS', 'RGBA',), - ('INPUTS', 'VECTOR',), - ('INPUTS', 'VALUE',), - ('OUTPUTS', 'MAIN',), - ('OUTPUTS', 'SHADER',), - ('OUTPUTS', 'RGBA',), - ('OUTPUTS', 'VECTOR',), - ('OUTPUTS', 'VALUE',), - ): - if src_sockets[inout][soctype] and dst_sockets[inout][soctype]: - if soctype == 'MAIN': - sc = src_sockets[inout][src_sockets[inout]['MAIN']] - dt = dst_sockets[inout][dst_sockets[inout]['MAIN']] - else: - sc = src_sockets[inout][soctype] - dt = dst_sockets[inout][soctype] - # start with 'dt' to determine number of possibilities. - for i, soc in enumerate(dt): - # if src main has enough entries - match them with dst main sockets by indexes. - if len(sc) > i: - matches[inout][soctype].append(((sc[i][1], sc[i][3]), (soc[1], soc[3]))) - # add 'VALUE_NAME' criterion to inputs. - if inout == 'INPUTS' and soctype == 'VALUE': - for s in sc: - if s[2] == soc[2]: # if names match - # append src (index, dval), dst (index, dval) - matches['INPUTS']['VALUE_NAME'].append(((s[1], s[3]), (soc[1], soc[3]))) - - # When src ['INPUTS']['MAIN'] is 'VECTOR' replace 'MAIN' with matches VECTOR if possible. - # This creates better links when relinking textures. - if src_sockets['INPUTS']['MAIN'] == 'VECTOR' and matches['INPUTS']['VECTOR']: - matches['INPUTS']['MAIN'] = matches['INPUTS']['VECTOR'] - - # Pass default values and RELINK: - for tp in ('MAIN', 'SHADER', 'RGBA', 'VECTOR', 'VALUE_NAME', 'VALUE'): - # INPUTS: Base on matches in proper order. - for (src_i, src_dval), (dst_i, dst_dval) in matches['INPUTS'][tp]: - # pass dvals - if src_dval and dst_dval and tp in {'RGBA', 'VALUE_NAME'}: - new_node.inputs[dst_i].default_value = src_dval - # Special case: switch to math - if node.type in {'MIX_RGB', 'ALPHAOVER', 'ZCOMBINE'} and\ - new_node.type == 'MATH' and\ - tp == 'MAIN': - new_dst_dval = max(src_dval[0], src_dval[1], src_dval[2]) - new_node.inputs[dst_i].default_value = new_dst_dval - if node.type == 'MIX_RGB': - if node.blend_type in [o[0] for o in operations]: - new_node.operation = node.blend_type - # Special case: switch from math to some types - if node.type == 'MATH' and\ - new_node.type in {'MIX_RGB', 'ALPHAOVER', 'ZCOMBINE'} and\ - tp == 'MAIN': - for i in range(3): - new_node.inputs[dst_i].default_value[i] = src_dval - if new_node.type == 'MIX_RGB': - if node.operation in [t[0] for t in blend_types]: - new_node.blend_type = node.operation - # Set Fac of MIX_RGB to 1.0 - new_node.inputs[0].default_value = 1.0 - # make link only when dst matching input is not linked already. - if node.inputs[src_i].links and not new_node.inputs[dst_i].links: - in_src_link = node.inputs[src_i].links[0] - in_dst_socket = new_node.inputs[dst_i] - connect_sockets(in_src_link.from_socket, in_dst_socket) - links.remove(in_src_link) - # OUTPUTS: Base on matches in proper order. - for (src_i, src_dval), (dst_i, dst_dval) in matches['OUTPUTS'][tp]: - for out_src_link in node.outputs[src_i].links: - out_dst_socket = new_node.outputs[dst_i] - connect_sockets(out_dst_socket, out_src_link.to_socket) - # relink rest inputs if possible, no criteria - for src_inp in node.inputs: - for dst_inp in new_node.inputs: - if src_inp.links and not dst_inp.links: - src_link = src_inp.links[0] - connect_sockets(src_link.from_socket, dst_inp) - links.remove(src_link) - # relink rest outputs if possible, base on node kind if any left. - for src_o in node.outputs: - for out_src_link in src_o.links: - for dst_o in new_node.outputs: - if src_o.type == dst_o.type: - connect_sockets(dst_o, out_src_link.to_socket) - # relink rest outputs no criteria if any left. Link all from first output. - for src_o in node.outputs: - for out_src_link in src_o.links: - if new_node.outputs: - connect_sockets(new_node.outputs[0], out_src_link.to_socket) - nodes.remove(node) - force_update(context) - return {'FINISHED'} - - class NWMergeNodes(Operator, NWBase): bl_idname = "node.nw_merge_nodes" bl_label = "Merge Nodes" @@ -2976,7 +2787,6 @@ classes = ( NWPreviewNode, NWFrameSelected, NWReloadImages, - NWSwitchNodeType, NWMergeNodes, NWBatchChangeNodes, NWChangeMixFactor, diff --git a/node_wrangler/preferences.py b/node_wrangler/preferences.py index 061514af3..6ce4c57bc 100644 --- a/node_wrangler/preferences.py +++ b/node_wrangler/preferences.py @@ -162,7 +162,6 @@ class NWNodeWrangler(bpy.types.AddonPreferences): # # REGISTER/UNREGISTER CLASSES AND KEYMAP ITEMS # -switch_category_menus = [] addon_keymaps = [] # kmi_defs entry: (identifier, key, action, CTRL, SHIFT, ALT, props, nice name) # props entry: (property name, property value) @@ -392,28 +391,8 @@ def register(): setattr(kmi.properties, prop, value) addon_keymaps.append((km, kmi)) - # switch submenus - switch_category_menus.clear() - for cat in node_categories_iter(None): - if cat.name not in ['Group', 'Script']: - idname = f"NODE_MT_nw_switch_{cat.identifier}_submenu" - switch_category_type = type(idname, (bpy.types.Menu,), { - "bl_space_type": 'NODE_EDITOR', - "bl_label": cat.name, - "category": cat, - "poll": cat.poll, - "draw": interface.draw_switch_category_submenu, - }) - - switch_category_menus.append(switch_category_type) - - bpy.utils.register_class(switch_category_type) - def unregister(): - for cat_types in switch_category_menus: - bpy.utils.unregister_class(cat_types) - switch_category_menus.clear() # keymaps for km, kmi in addon_keymaps: -- 2.30.2