├── README.md ├── remove_unused_nodes.py └── replacing_addone.py /README.md: -------------------------------------------------------------------------------- 1 | # Blender-Bulk-Texture-Replacer 2 | ### If you are using Blender 4.0, download the **replacing_addone.py** directly from repository and install it like usual. If you do not see the Python file in the Blender Addon Installation Window make a zip of this Python file. 3 | Install the Tool. 4 | 5 | The Convertor should be inside the "Tool" UI. 6 | 7 | ## Bulk Texture Replacer 8 | >> 1. It can replace bulk replace textures with your input name 9 | >> 2. Another use case, suppose you have a texture image which is applied to a lot of objects, you can run this addon to rename the texture to your new one, basically Remapping the texture with your new one. Works like Remap user in blender file API. 10 | Before Using: 11 | Use a convertor tool to convert all your texture files into whatever you want 12 | 13 | Usage: 14 | 1. Click on Replace button 15 | 2. A Dialog Will appear. 16 | 3. In Original (which is current extension) put the extension name. 17 | 4. In Resultant (Which you want to replace to) put the next extension name. 18 | 5. Press Enter or OK or LMB on 3D viewport. 19 | 6. Now, File > External Data > Find Missing File and go where your converted texture files are. 20 | 21 | This should bulk replace all the texture files. 22 | 23 | ## New Feature: Bulk Blend Type Changer 24 | 25 | Added Bulk Blend Type Change Feature. 26 | 27 | This "Change" feature should be just below your "Bulk Text Replacer". 28 | 29 | Usage: 30 | 1. Click on Change Button. 31 | 2. A Dialog will appear. 32 | 3. In Original, select the Blend Type from which you want to Change (All: for replacing all the Blend Type) 33 | 4. In Resultant, select the type you want to convert to. 34 | 5. Click "OK" 35 | 36 | ## New Feature: Bulk Rename Objects 37 | Works like above. 38 | 39 | # Remove Unused Nodes 40 | ```Use this on the Scripting Tab on Blender. Copy-Paste the Code and Run. ``` 41 | Removes the unused nodes from the shader editor of all the materials. 42 | 43 | ## If you run into Error please raise an issue. But before that please copy the errors from "System Console Window" and paste in the issue. 44 | -------------------------------------------------------------------------------- /remove_unused_nodes.py: -------------------------------------------------------------------------------- 1 | import bpy 2 | 3 | # Enable the Node Wrangler add-on 4 | bpy.ops.preferences.addon_enable(module='node_wrangler') 5 | 6 | def delete_unused_nodes(material): 7 | node_tree = material.node_tree 8 | nodes_to_remove = [] 9 | 10 | for node in node_tree.nodes: 11 | if not node.outputs: 12 | continue 13 | 14 | has_linked_output = any([output.is_linked for output in node.outputs]) 15 | 16 | if not has_linked_output: 17 | nodes_to_remove.append(node) 18 | 19 | for node in nodes_to_remove: 20 | node_tree.nodes.remove(node) 21 | 22 | # Iterate through all materials in the blend file 23 | for material in bpy.data.materials: 24 | if material.use_nodes: 25 | delete_unused_nodes(material) 26 | -------------------------------------------------------------------------------- /replacing_addone.py: -------------------------------------------------------------------------------- 1 | bl_info = { 2 | "name": "Bulk Replace", 3 | "author": "Satyam", 4 | "version": (1, 2), 5 | "blender": (3, 0, 0), 6 | "location": "View3D > Tool > Replace Texture(s)", 7 | "description": "Bulk Replace the Texture \n Bulk convert Blend Mode \n Bulk Name Replace", 8 | "warning": "", 9 | "doc_url": "https://github.com/vsatyamesc/Blender-Bulk-Texture-Replacer/blob/main/README.md", 10 | "category": "Tool", 11 | } 12 | 13 | import bpy 14 | from bpy.types import (Panel, Operator) 15 | from bpy.utils import register_class, unregister_class 16 | from bpy.props import (StringProperty,BoolProperty,IntProperty,FloatProperty,EnumProperty) 17 | 18 | class RANOperator(bpy.types.Operator): 19 | """Replaces the Texture to whatever you want""" 20 | bl_idname = "cobject.cs1" 21 | bl_label = "Converter" 22 | Original: StringProperty( 23 | name="Original", 24 | default=".dds", 25 | description="the extension name with '.' before it", 26 | ) # you could add more of these 27 | 28 | Resultant: StringProperty( 29 | name="Resultant", 30 | default=".png", 31 | description="the extension name with '.' before it", 32 | ) # you can add more of these 33 | 34 | def execute(self, context): 35 | for i in bpy.data.images: 36 | try: 37 | i.filepath = i.filepath.replace(self.Original, self.Resultant) 38 | i.name = i.name.replace(self.Original, self.Resultant) 39 | print("done") 40 | except: 41 | print("replace failed") 42 | return {'FINISHED'} 43 | def invoke(self, context, event): 44 | wm = context.window_manager 45 | return wm.invoke_props_dialog(self) 46 | 47 | class ReANOperator(bpy.types.Operator): 48 | """Renames/Changes part of name to whatever you want""" 49 | bl_idname = "cobject.cs3" 50 | bl_label = "Rename/Replace" 51 | Original: StringProperty( 52 | name="Original", 53 | default="Defualt", 54 | description="File Name, or the word that you want to replace", 55 | ) 56 | 57 | Resultant: StringProperty( 58 | name="Resultant", 59 | default="Final", 60 | description="New Name", 61 | ) 62 | 63 | def execute(self, context): 64 | i = 0 65 | for obj in bpy.data.objects: 66 | i=i+1 67 | if self.Original in obj.name: 68 | try: 69 | obj.name = str(obj.name).replace(self.Original,self.Resultant) 70 | except: 71 | print("Error Occured at " + obj.name ) 72 | else: 73 | pass 74 | if i == len(bpy.data.objects)-1: 75 | break 76 | return {'FINISHED'} 77 | 78 | def invoke(self, context, event): 79 | wm = context.window_manager 80 | return wm.invoke_props_dialog(self) 81 | 82 | class BANOperator(bpy.types.Operator): 83 | """Replaces the Texture to whatever you want""" 84 | bl_idname = "cobject.cs2" 85 | bl_label = "Changer" 86 | inz_initial: bpy.props.EnumProperty( 87 | name="Original", 88 | description='Select the Blend Type of your Object', 89 | items = [ 90 | ("0","All", "Every Blend type"), 91 | ("1","Blend", "Alpha Blend type"), 92 | ("2","Hashed", "Alpha Hashed type"), 93 | ("3","Clip", "Alpha Clip type"), 94 | ("4","Opaque", "Opaque type") 95 | ] 96 | ) 97 | inz_final: bpy.props.EnumProperty( 98 | name="Final", 99 | description='Select the Blend Type of your Object', 100 | items = [ 101 | ("1","Blend", "Alpha Blend type"), 102 | ("2","Hashed", "Alpha Hashed type"), 103 | ("3","Clip", "Alpha Clip type"), 104 | ("4","Opaque", "Opaque type") 105 | ] 106 | ) 107 | def blendmd_chk(self,initial=None,final=None): 108 | switcher = {"0":"All", "1":"BLEND","2":"HASHED","3":"CLIP","4":"OPAQUE"} 109 | initial = switcher[initial] 110 | if initial == "All" or None: 111 | initial = ["BLEND","HASHED","CLIP","OPAQUE"] 112 | else: 113 | pass 114 | if final == None: 115 | final = switcher["4"] 116 | final = switcher[final] 117 | return [initial, final] 118 | 119 | def execute(self, context): 120 | context = bpy.context 121 | res = self.blendmd_chk(self.inz_initial,self.inz_final) 122 | print(res) 123 | try: 124 | for o in bpy.data.materials: 125 | if res[0] == res[1]: 126 | pass 127 | elif isinstance(res[0],list): 128 | if o.blend_method in res[0]: 129 | o.blend_method = res[1] 130 | else: 131 | if o.blend_method is None: 132 | print("Object"+str(o)+"is NoneType") 133 | elif o.blend_method == res[0]: 134 | o.blend_method = res[1] 135 | else: 136 | print("Error processing object : "+str(o)) 137 | except: 138 | print("Tis Not Working") 139 | return {'FINISHED'} 140 | 141 | def invoke(self, context, event): 142 | wm = context.window_manager 143 | return wm.invoke_props_dialog(self) 144 | 145 | def draw(self, context): 146 | layout = self.layout 147 | col = layout.column() 148 | col.label(text="Convert From") 149 | row = col.row() 150 | row.prop(self, "inz_initial") 151 | 152 | col.label(text="Convert To") 153 | col.prop(self, "inz_final") 154 | 155 | 156 | class COS_PT_gg(bpy.types.Panel): 157 | bl_label = "Replace Texture(s)" 158 | bl_idname = "cobject_PT_" 159 | bl_space_type = 'VIEW_3D' 160 | bl_region_type = 'UI' 161 | bl_category = "Tool" 162 | 163 | def draw(self, context): 164 | layout = self.layout 165 | row = layout.row() 166 | row.operator(RANOperator.bl_idname, text = "Replace", icon = "UV_SYNC_SELECT") 167 | 168 | class COS1_PT_gg(bpy.types.Panel): 169 | bl_label = "Change Blend Mode" 170 | bl_idname = "cobject_PT1_" 171 | bl_space_type = 'VIEW_3D' 172 | bl_region_type = 'UI' 173 | bl_category = "Tool" 174 | 175 | def draw(self, context): 176 | layout = self.layout 177 | row = layout.row() 178 | row.operator(BANOperator.bl_idname, text = "Change", icon = "GP_MULTIFRAME_EDITING") 179 | 180 | class COS2_PT_gg(bpy.types.Panel): 181 | bl_label = "Rename Objects" 182 | bl_idname = "cobject_PT2_" 183 | bl_space_type = 'VIEW_3D' 184 | bl_region_type = 'UI' 185 | bl_category = "Tool" 186 | 187 | def draw(self, context): 188 | layout = self.layout 189 | row = layout.row() 190 | row.operator(ReANOperator.bl_idname, text = "Rename", icon = "OUTLINER_DATA_GP_LAYER") 191 | 192 | _classes = [ RANOperator,ReANOperator, BANOperator, COS_PT_gg, COS1_PT_gg,COS2_PT_gg] 193 | 194 | def register(): 195 | for cls in _classes: 196 | register_class(cls) 197 | 198 | def unregister(): 199 | for cls in _classes: 200 | unregister_class(cls) 201 | 202 | if __name__ == "__main__": 203 | register() 204 | --------------------------------------------------------------------------------