Batch auto renaming materials to object name

Hi all,

I got a Python script renaming materials to their following objects. This is useful when I bring in Alembics from Maya -
I set up a scene re-naming all the materials to the object it’s applied to, then bring in alembics so the materials get auto-applied to the objects in the alembic without having to do it one by one.

The only problem is that I have to do this one by one with every object.
The pipeline would be much more streamlined if I could auto rename all of the materials at once.
I’d like to know if there is a script for this? or is there any way to modify my existing script to do so.

Here is the script I’m using. (Courtesy of Alexey Khlystov)
http://alexiy.nl/renamer

import bpy

def log(text):
	if bpy.context.preferences.addons[__name__].preferences.pref_log:
		print('Renamer: '+text)
	return {'FINISHED'}

class renamer_preferences(bpy.types.AddonPreferences):
	bl_idname = __name__
	pref_log: bpy.props.BoolProperty(
			name = 'Logging',
			description = 'Logging to the console',
			default = False)

	pref_pfs: bpy.props.BoolProperty(
			name = 'Prefix-Suffix field',
			description = 'Show the name Prefix-Suffix field',
			default = True)

	pref_top: bpy.props.BoolProperty(
			name = 'Always on top (after Blender reload)',
			description = 'Show the Renamer panel always on top properties area',
			default = True)

	pref_smp: bpy.props.BoolProperty(
			name = 'Simplified panel (after Blender reload)',
			description = 'Show the simplified buttons on the Renamer panel',
			default = False)

	def draw(self, context):
		self.layout.prop(self, 'pref_log')
		self.layout.prop(self, 'pref_pfs')
		self.layout.prop(self, 'pref_top')
		self.layout.prop(self, 'pref_smp')

		self.layout.operator('wm.url_open', text='mmm... donuts ;)', icon='MESH_TORUS').url = 'https://money.yandex.ru/to/41001993857335'

bpy.utils.register_class(renamer_preferences)

on_top = 'HIDE_HEADER'
icon_up = 'NONE'
icon_down = 'NONE'
icon_sngl = 'NONE'
text_up = 'Name to object'
text_down = 'Name from object'
text_sngl = 'Single-user copy'
text_none = 'No name source'
align = 'LEFT'
if __name__ in bpy.context.preferences.addons:
	if not(bpy.context.preferences.addons[__name__].preferences == None):
		if not bpy.context.preferences.addons[__name__].preferences.pref_top:
			on_top = 'DEFAULT_CLOSED'
		if bpy.context.preferences.addons[__name__].preferences.pref_smp:
			icon_up = 'TRIA_UP'
			icon_down = 'TRIA_DOWN'
			icon_sngl = 'FILE_NEW'
			text_up = ''
			text_down = ''
			text_sngl = ''
			text_none = ''
			align = 'RIGHT'

#Data
class PanelDat(bpy.types.Panel):
	bl_idname = 'OBJECT_PT_PanelDat'
	bl_space_type = 'PROPERTIES'
	bl_region_type = 'WINDOW'
	bl_context = 'data'
	bl_label = 'Renamer'
	bl_options = {on_top}

	def draw(self, context):
		scene = context.scene
		layout = self.layout
		row = layout.row()
		row.alignment = align

		if context.active_object.data:

			if bpy.context.preferences.addons[__name__].preferences.pref_pfs: row.prop(scene, 'renamer_pfs', text='')

			to = row.operator('renamer.action', icon=icon_up, text=text_up)
			to.state = 'dat'
			to.object_target = True

			fo = row.operator('renamer.action', icon=icon_down, text=text_down)
			fo.state = 'dat'
			fo.object_target = False

			row.prop(scene, 'renamer_single', icon=icon_sngl, text=text_sngl)
		else:
			row.label(text=text_none)

#Material
class PanelMat(bpy.types.Panel):
	bl_idname = 'OBJECT_PT_PanelMat'
	bl_space_type = 'PROPERTIES'
	bl_region_type = 'WINDOW'
	bl_context = 'material'
	bl_label = 'Renamer'
	bl_options = {on_top}

	def draw(self, context):
		scene = context.scene
		layout = self.layout
		row = layout.row()
		row.alignment = align

		if len(context.active_object.data.materials) != 0 and context.object.active_material != None:

			if bpy.context.preferences.addons[__name__].preferences.pref_pfs: row.prop(scene, 'renamer_pfs', text='')

			to = row.operator('renamer.action', icon=icon_up, text=text_up)
			to.state = 'mat'
			to.object_target = True

			fo = row.operator('renamer.action', icon=icon_down, text=text_down)
			fo.state = 'mat'
			fo.object_target = False

			row.prop(scene, 'renamer_single', icon=icon_sngl, text=text_sngl)
		else:
			row.label(text=text_none)

#Particles
class PanelPat(bpy.types.Panel):
	bl_idname = 'OBJECT_PT_PanelPat'
	bl_space_type = 'PROPERTIES'
	bl_region_type = 'WINDOW'
	bl_context = 'particle'
	bl_label = 'Renamer'
	bl_options = {on_top}

	def draw(self, context):
		scene = context.scene
		layout = self.layout
		row = layout.row()
		row.alignment = align

		if len(context.active_object.particle_systems) != 0 and context.active_object.particle_systems.active != None:

			if bpy.context.preferences.addons[__name__].preferences.pref_pfs: row.prop(scene, 'renamer_pfs', text='')

			to = row.operator('renamer.action', icon=icon_up, text=text_up)
			to.state = 'pat'
			to.object_target = True

			fo = row.operator('renamer.action', icon=icon_down, text=text_down)
			fo.state = 'pat'
			fo.object_target = False

		else:
			row.label(text=text_none)

#Texture
class PanelTex(bpy.types.Panel):
	bl_idname = 'OBJECT_PT_PanelTex'
	bl_space_type = 'PROPERTIES'
	bl_region_type = 'WINDOW'
	bl_context = 'texture'
	bl_label = 'Renamer'
	bl_options = {on_top}

	def draw(self, context):
		scene = context.scene
		tool = context.tool_settings
		layout = self.layout
		row = layout.row()
		row.alignment = align

		obj = context.active_object != None
		tx = None

		if obj:
			mode = context.active_object.mode
			if mode == "SCULPT": tx = tool.sculpt.brush.texture != None
			if mode == "TEXTURE_PAINT": tx = tool.image_paint.brush.texture != None
			if mode == "VERTEX_PAINT": tx = tool.vertex_paint.brush.texture != None
			if mode == "WEIGHT_PAINT": tx = tool.weight_paint.brush.texture != None

		if tx:
			if bpy.context.preferences.addons[__name__].preferences.pref_pfs: row.prop(scene, 'renamer_pfs', text='')

			to = row.operator('renamer.action', icon=icon_up, text=text_up)
			to.state = 'tex'
			to.object_target = True

			fo = row.operator('renamer.action', icon=icon_down, text=text_down)
			fo.state = 'tex'
			fo.object_target = False

			row.prop(scene, 'renamer_single', icon=icon_sngl, text=text_sngl)
		else:
			row.label(text=text_none)

def rename(state: str, object_target: bool, context):
	data = bpy.data
	single = context.scene.renamer_single
	object = context.active_object

	target = None
	if object_target:
		target = object
	else:
		name = object.name

	if state == 'dat':
		if single and (not object_target): context.object.data = context.object.data.copy()
		if not target:
			target = context.object.data
		else:
			name = context.object.data.name
	elif state == 'mat':
		if single and (not object_target): context.object.active_material = context.object.active_material.copy()
		if not target:
			target = context.object.active_material
		else:
			name = context.object.active_material.name
	elif state == 'pat':
		if not target:
			target = context.active_object.particle_systems.active
		else:
			name = context.active_object.particle_systems.active.name
	elif state == 'tex':
		tool = context.tool_settings
		if single and (not object_target):
			mode = context.active_object.mode
			if mode == "SCULPT": tool.sculpt.brush.texture = tool.sculpt.brush.texture.copy()
			if mode == "TEXTURE_PAINT": tool.image_paint.brush.texture = tool.image_paint.brush.texture.copy()
			if mode == "VERTEX_PAINT": tool.vertex_paint.brush.texture = tool.vertex_paint.brush.texture.copy()
			if mode == "WEIGHT_PAINT": tool.weight_paint.brush.texture = tool.weight_paint.brush.texture.copy()
		if not target:
			mode = context.active_object.mode
			if mode == "SCULPT": target = tool.sculpt.brush.texture
			if mode == "TEXTURE_PAINT": target = tool.image_paint.brush.texture
			if mode == "VERTEX_PAINT": target = tool.vertex_paint.brush.texture
			if mode == "WEIGHT_PAINT": target = tool.weight_paint.brush.texture
		else:
			mode = context.active_object.mode
			if mode == "SCULPT": name = tool.sculpt.brush.texture.name
			if mode == "TEXTURE_PAINT": name = tool.image_paint.brush.texture.name
			if mode == "VERTEX_PAINT": name = tool.vertex_paint.brush.texture.name
			if mode == "WEIGHT_PAINT": name = tool.weight_paint.brush.texture.name

	if bpy.context.preferences.addons[__name__].preferences.pref_pfs and context.scene.renamer_pfs:
		pfs = context.scene.renamer_pfs
		pos = pfs.find('*')
		p = pfs[0:pos]
		s = pfs[pos+1:len(pfs)]

		name = p+name+s

	log('Target - '+str(target)+' / Source - '+str(name)+' / Single - '+str(single))
	target.name = name

	return{'FINISHED'}

class ActionRename(bpy.types.Operator):
	bl_idname = 'renamer.action'
	bl_label = 'Rename'
	bl_description = 'Transfer the name'

	props = bpy.props
	state = props.StringProperty()
	object_target = props.BoolProperty()

	def execute(self, context):
		rename(self.state, self.object_target, context)
		return {'FINISHED'}

classes = (
	PanelDat,
	PanelMat,
	PanelPat,
	PanelTex,
	ActionRename,
)

def register():

	bpy.types.Scene.renamer_single = bpy.props.BoolProperty(
		name='Single-user copy',
		description='Make a single user-copy',
		default = False)

	bpy.types.Scene.renamer_pfs = bpy.props.StringProperty(
		name='Prefix-Suffix field',
		description='"prefix*suffix" - where "*" will be source name',
		default = '*')

	for item in classes:
		print('register')
		bpy.utils.register_class(item)

	print('register END')

def unregister():

	del (	bpy.types.Scene.renamer_single,
			bpy.types.Scene.renamer_pfs,
		)

	for item in classes:
		bpy.utils.unregister_class(item)

I haven’t looked through all of your code, but scanning through it I can see that you have an operator that is calling a function called rename on a specific object that you’re passing via a property:
rename(self.state, self.object_target, context)

instead, just loop through all objects and skip the property entirely:

for o in bpy.data.objects:
    rename(self.state, o, context)

the rename function likely also needs to be updated because it appears to be making some assumptions about the current context, but it shouldn’t be too hard to figure out if you’ve got any experience with python.

This plugin needs to be updated for 2.93.
It would be nice, if original creator were informed about it.
Although any help is appreciated.

It’s been updated…

1 Like