renaming datablocks with python


(zenoscope) #1

I’m being lazy, and trying to hack Campbell Barton’s renaming script so that I can rename the datablock as well as the object’s name.
Is there any way of renaming a datablock using python?


(ideasman42) #2

Hi, this is Campbell Barton
This is fairly simple, mabe could add to my script by default, a Rename data option.


ob.name = newName
data = ob.getData()
data.name = newName
if ob.getType() == 'Mesh' # Need to update NMesh data.
    data.update()


(zenoscope) #3

Thank you so much! I had missed the data.update() part.
Here is my update to your script.


#!BPY

"""
Name: 'Batch Object Name Edit'
Blender: 232
Group: 'Object'
Tooltip: 'Apply the chosen rule to rename all selected objects at once'
"""

__author__ = "Campbell Barton"
__url__ = ("blender", "elysiun")
__version__ = "1.0"

__bpydoc__ = """\
"Batch Object Name Edit" allows you to change multiple names of Blender
objects at once.  It provides options to define if you want to: replace text
in the current names, truncate their beginnings or endings or prepend / append
strings to them.

Usage:

Select the objects to be renamed and run this script from the Object->Scripts
menu of the 3d View.
"""

# $Id: batch_name_edit.py,v 1.3 2004/11/07 12:46:04 ianwill Exp $
#
# --------------------------------------------------------------------------
# Batch Name Edit by Campbell Barton (AKA Ideasman)
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------

from Blender import *
from Blender import NMesh

def replace():
 replace = Draw.PupStrInput('Replace: ', '', 32)
 if replace == None: return
  
 with = Draw.PupStrInput('With: ', '', 32)
 if with == None: return
 
 for ob in Object.GetSelected():
  
  if replace in ob.name:
   chIdx = ob.name.index(replace)
   
   # Remove the offending word and replace it with - 'with'
   ob.name = ob.name[ :chIdx] + with + ob.name[chIdx + len(replace):]
      

def ren_datablock_to_obj_name():
 for ob in Object.GetSelected():
  data = ob.getData()
  data.name = ob.name
  if ob.getType() == 'Mesh': 
  # Need to update NMesh data. 
   data.update()
   
def ren_obj_to_datablock_name():
 for ob in Object.GetSelected():
  data = ob.getData()  
  ob.name = data.name
   
def prefix():
 prefix = Draw.PupStrInput('prefix: ', '', 32)
 if prefix == None: return
 
 for ob in Object.GetSelected():
  ob.name = prefix + ob.name  
  data = ob.getData()


def suffix():
 suffix = Draw.PupStrInput('Suffix: ', '', 32)
 if suffix == None: return
 
 for ob in Object.GetSelected():
  ob.name = ob.name + suffix

def truncate_start():
 truncate = Draw.PupIntInput('Truncate Start: ', 0, 0, 31)
 if truncate != None:
  for ob in Object.GetSelected():
   ob.name = ob.name[truncate: ]

def truncate_end():
 truncate = Draw.PupIntInput('Truncate End: ', 0, 0, 31)
 if truncate == None: return
 
 for ob in Object.GetSelected():
  ob.name = ob.name[ :-truncate]

name = "Selected Object Names%t|Replace Text|Add Prefix|Add Suffix|Truncate Start|Truncate End|Replace DataBlock name with Obj|replace Obj name with Datablock"
result = Draw.PupMenu(name)

if result == -1:
 pass
elif result == 1:
 replace()
elif result == 2:
 prefix()
elif result == 3:
 suffix()
elif result == 4:
 truncate_start()
elif result == 5:
 truncate_end()
elif result == 6:
 ren_datablock_to_obj_name()
elif result == 7: 
 ren_obj_to_datablock_name()


(ideasman42) #4

Argh- we both did the same thing-

I noticed the script you used was based on an old version- A new version was released in 2.36.


#!BPY



"""

Name: 'Batch Object Name Edit'

Blender: 232

Group: 'Object'

Tooltip: 'Apply the chosen rule to rename all selected objects at once.'

"""



__author__ = "Campbell Barton"

__url__ = ("blender", "elysiun")

__version__ = "1.0"



__bpydoc__ = """\

"Batch Object Name Edit" allows you to change multiple names of Blender

objects at once.  It provides options to define if you want to: replace text

in the current names, truncate their beginnings or endings or prepend / append

strings to them.



Usage:



Select the objects to be renamed and run this script from the Object->Scripts

menu of the 3d View.

"""





# $Id: batch_name_edit.py,v 1.4 2004/12/01 04:49:04 ianwill Exp $

#

# --------------------------------------------------------------------------

# Batch Name Edit by Campbell Barton (AKA Ideasman)

# --------------------------------------------------------------------------

# ***** BEGIN GPL LICENSE BLOCK *****

#

# This program is free software; you can redistribute it and/or

# modify it under the terms of the GNU General Public License

# as published by the Free Software Foundation; either version 2

# of the License, or (at your option) any later version.

#

# This program is distributed in the hope that it will be useful,

# but WITHOUT ANY WARRANTY; without even the implied warranty of

# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

# GNU General Public License for more details.

#

# You should have received a copy of the GNU General Public License

# along with this program; if not, write to the Free Software Foundation,

# Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

#

# ***** END GPL LICENCE BLOCK *****

# --------------------------------------------------------------------------



from Blender import *


global renameCount
renameCount = 0

def main():
	global renameCount
	# Rename the datablocks that are used by the object.
	def renameLinkedDataFromObject():
		name = "Rename Data to Object Name%t|Rename Linked Datablocks%x1|Leave Linked Data Names as is%x0"
		result = Draw.PupMenu(name)
		if result == -1:
			return
		if result == 0:
			return
			
		# Result 1, we want to rename data
		for ob in Object.GetSelected():
			if ob.name == ob.getData(1):
				return # Alredy the same name, dont bother.
				
			try:
				data = ob.getData()
				data.name = ob.name
				if ob.getType() == 'Mesh':
					# update, keep edges if they exist.
					data.update(0, (data.edges != []), 0)
			except:
				# Maybe trying to renasme an empty, dont worry about this.
				pass
		
	
	

	def new():
		global renameCount

		newname = Draw.PupStrInput('Name: ', '', 32)

		if newname == None: return
		Window.WaitCursor(1)

		for ob in Object.GetSelected():

			if ob.name != newname:
				ob.name = newname
				renameCount+=1
		

	def replace():
		global renameCount
		co = Window.GetMouseCoords()		

		
		replace = Draw.PupStrInput('Replace: ', '', 32)

		if replace == None: return
		
		Window.SetMouseCoords(co)
		

		with = Draw.PupStrInput('With: ', '', 32)

		if with == None: return

		Window.WaitCursor(1)

		for ob in Object.GetSelected():
			newname = ob.name.replace(replace, with)
			if ob.name != newname:
				ob.name = newname
				renameCount+=1
			

	

	def prefix():
		global renameCount

		prefix = Draw.PupStrInput('prefix: ', '', 32)
		

		if prefix == None or prefix == '': return

		Window.WaitCursor(1)

		for ob in Object.GetSelected():
			ob.name = prefix + ob.name
			renameCount+=1 # we knows these are different.

	

	def suffix():
		global renameCount

		suffix = Draw.PupStrInput('Suffix: ', '', 32)

		if suffix == None: return

		Window.WaitCursor(1)

		for ob in Object.GetSelected():
			newname = ob.name + suffix
			if ob.name != newname:
				ob.name = newname
				renameCount+=1			
			

	

	def truncate_start():
		global renameCount

		truncate = Draw.PupIntInput('Truncate Start: ', 0, 0, 31)

		if truncate == None:
			return
		Window.WaitCursor(1)

		
		for ob in Object.GetSelected():

			newname = ob.name[truncate: ]
			if ob.name != newname:
				ob.name = newname
				renameCount+=1							

	

	def truncate_end():
		global renameCount

		truncate = Draw.PupIntInput('Truncate End: ', 0, 0, 31)

		if truncate == None: return

		Window.WaitCursor(1)

		for ob in Object.GetSelected():

			newname = ob.name[ :-truncate]
			if ob.name != newname:
				ob.name = newname
				renameCount+=1	

	def renameObjectFromLinkedData():
		global renameCount
		Window.WaitCursor(1)
		
		for ob in Object.GetSelected():
			newname = ob.getData(1)
			if ob.name != newname:
				ob.name = newname
				renameCount+=1	
		
	
	

	name = "Selected Object Names%t|New Name|Replace Text|Add Prefix|Add Suffix|Truncate Start|Truncate End|Rename Objects to Data Names"

	result = Draw.PupMenu(name)

	

	if result == -1:

		return

	elif result == 1:

		new()
		renameLinkedDataFromObject()

	elif result == 2:

		replace()
		renameLinkedDataFromObject()

	elif result == 3:

		prefix()
		renameLinkedDataFromObject()

	elif result == 4:

		suffix()
		renameLinkedDataFromObject()

	elif result == 5:

		truncate_start()
		renameLinkedDataFromObject()

	elif result == 6:

		truncate_end()
		renameLinkedDataFromObject()
	elif result == 7:
		renameObjectFromLinkedData()

	
	Draw.PupMenu('renamed: %d objects.' % renameCount)
	
	Window.WaitCursor(0)

main()



(zenoscope) #5

haha, classic!
I’ve noticed there need to be an error handler in the script, but I see the new script has it updated already. I’m making dancing robots, each with different bodyparts that need to be renamed (both objects and datablocks), and this script has been a godsend.


(zenoscope) #6

its probably not the right place to put it, but i’ll put it here anyway. this is an update to the batch_name_edit script that lets you do exactly the same things to both object names and datablock names. it’ll also generate a list of the names of selected objects as well. if i can figure out how to get blender python to make a selection, i’ll upgrade the script so that you can select indivdual objects from that list.


#!BPY 
""" 
Name: 'Batch Object Name Edit' 
Blender: 232 
Group: 'Object' 
Tip: 'Apply the chosen rule to rename all selected objects at once.' 
"""
__author__ = "Campbell Barton" 
__url__ = ("blender", "elysiun") 
__version__ = "1.0" 
__bpydoc__ = """\ 
"Batch Object Name Edit" allows you to change multiple names of Blender 
objects at once.  It provides options to define if you want to: replace text 
in the current names, truncate their beginnings or endings or prepend / append 
strings to them. 
 
Usage: 
Select the objects to be renamed and run this script from the Object->Scripts 
menu of the 3d View.  
""" 
 
# $Id: batch_name_edit.py,v 1.4 2004/12/01 04:49:04 ianwill Exp $ 
# 
# -------------------------------------------------------------------------- 
# Batch Name Edit by Campbell Barton (AKA Ideasman) 
# -------------------------------------------------------------------------- 
# ***** BEGIN GPL LICENSE BLOCK ***** 
# 
# This program is free software; you can redistribute it and/or 
# modify it under the terms of the GNU General Public License 
# as published by the Free Software Foundation; either version 2 
# of the License, or (at your option) any later version. 
# 
# This program is distributed in the hope that it will be useful, 
# but WITHOUT ANY WARRANTY; without even the implied warranty of 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
# GNU General Public License for more details. 
# 
# You should have received a copy of the GNU General Public License 
# along with this program; if not, write to the Free Software Foundation, 
# Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. 
# 
# ***** END GPL LICENCE BLOCK ***** 
# -------------------------------------------------------------------------- 

"""/
Change history:
added code to rename objects and datablocks in the same ways (replace text, truncate etc)
added "list" option so you can check the names of objects/data quickly
changed the behaviour of the "rename count" so it doesn't pop up if you are listing objects
 or quit before you commit a change.
 
Also, if you click on a name in the list then it selects the object as well.
"""

from Blender import * 
  
global renameCount 
renameCount = -1 

def main(): 
   global renameCount 
   # Rename the datablocks that are used by the object. 

def new(change):
   global renameCount 
   newname = Draw.PupStrInput('Name: ', '', 19) #19 for data and 
   if newname == None: return 
   Window.WaitCursor(1)
   renameCount = 0

   for ob in Object.GetSelected():
	if change == "Object":	 
	 renameObject(ob,ob.name)
	elif change == "Data":
	 data = ob.getData()
	 renameData(ob,data.name)

def replace(change):
   global renameCount   
   co = Window.GetMouseCoords()       
        
   replace = Draw.PupStrInput('Replace: ', '', 19)     
   if replace == None: return        
   Window.SetMouseCoords(co)        
 
   with = Draw.PupStrInput('With: ', '', 19)
   if with == None: return 
   Window.WaitCursor(1) 
   renameCount = 0
 
   for ob in Object.GetSelected():
	if change == "Object":
	 print replace
	 print with
	 renameObject(ob,ob.name.replace(replace, with))
	elif change == "Data":
	 print replace
	 print with
	 # need to use the python code for this....
	 data = ob.getData()
	 if replace in data.name: 
	  chIdx = data.name.index(replace)
	  print "chd " + str(chIdx)
	    # Remove the offending word and replace it with - 'with' 	 
	  renameData(ob,data.name[:chIdx] + with + data.name[chIdx + len(replace):])          
 
def prefix(change):
   global renameCount 
   prefix = Draw.PupStrInput('Prefix: ', '', 19)         
 
   if prefix == None or prefix == '': return 
   Window.WaitCursor(1) 
   renameCount = 0
 
   for ob in Object.GetSelected():
	if change == "Object":	 
	 renameObject(ob,prefix + ob.name)
	elif change == "Data":
	 data = ob.getData()
	 renameData(ob,prefix + data.name)      
  
 
def suffix(change):
   global renameCount   
   suffix = Draw.PupStrInput('Suffix: ', '', 19) 
 
   if suffix == None: return  
   Window.WaitCursor(1) 
   renameCount = 0
 
   for ob in Object.GetSelected():
	if change == "Object":	 
	 renameObject(ob,ob.name + suffix)
	elif change == "Data":
	 data = ob.getData()
	 renameData(ob,data.name+ suffix)      

      
def truncate_end(change):
   global renameCount 
   truncate = Draw.PupIntInput('Truncate End: ', 0, 0, 19) 
   if truncate == None: return 
   Window.WaitCursor(1)
   renameCount = 0
 
   for ob in Object.GetSelected():
	if change == "Object":	 
	 renameObject(ob,ob.name[ :-truncate])	 
	elif change == "Data":
	 data = ob.getData()
	 renameData(ob,data.name[ :-truncate])      

def truncate_start(change):
   global renameCount 
   truncate = Draw.PupIntInput('Truncate Start: ', 0, 0, 19)  
   if truncate == None:return 
   Window.WaitCursor(1)
   renameCount = 0
   
   for ob in Object.GetSelected():
	if change == "Object":	 
	 renameObject(ob,ob.name[truncate: ])	 
	elif change == "Data":
	 data = ob.getData()
	 renameData(ob,data.name[truncate: ])
	
def list_names(change):
   list="List names of" + change + "%t"
   
   for ob in Object.GetSelected():
	if change == "Object":	 
	 list = list + "|" + ob.name
	elif change == "Data":
	 data = ob.getData()
	 list = list + "|" + data.name
	 
   #list = list
   print list
   Draw.PupMenu(list,20)  
	 	
def renameData(ob,newname):
 global renameCount  
 if ob.name == ob.getData(): 
  return # Alredy the same name, dont bother.
 try: 
  data = ob.getData()	  
  data.name = newname
  data.update()
  renameCount+=1 # doesn't seem to work right, neither does it count right in the object to data copy
  if ob.getType() == 'Mesh':
	# update, keep edges if they exist.
   data.update(0, (data.edges != []), 0)  
 except: # Maybe trying to rename an empty, dont worry about this. 
  pass

def renameObject(ob,newname):
   global renameCount 
   if ob.name != newname: 
      ob.name = newname
      renameCount+=1

	 
def renameObjectFromLinkedData(change):
   global renameCount 
   Window.WaitCursor(1)
   renameCount = 0

   for ob in Object.GetSelected():
	if change == "Object":
	 data = ob.getData()
	 renameObject(ob,data.name)
	elif change == "Data":
	 newname = ob.name
	 renameData(ob,newname)
       
name = "rename%t|Objects|Data"
result = Draw.PupMenu(name) 
if result == -1:
  pass
elif result == 1:
	change = "Object"
	keep = "Data"
elif result == 2:
	change = "Data"
	keep = "Object"

name = "Selected "+change+" Names%t|New Name|Replace Text|Add Prefix|Add Suffix|Truncate Start|Truncate End|Copy "+ change +" to "+ keep +" Names|List Names"

result = Draw.PupMenu(name) 
if result == -1:
  pass
elif result == 1:  
  #new(change)
  Draw.PupMenu("??%t|Dunno what this is| supposed to do,|so its gone for now") 
elif result == 2:   
  replace(change)
elif result == 3:   
  prefix(change)  
elif result == 4:   
  suffix(change)
elif result == 5:   
  truncate_start(change)
elif result == 6:   
  truncate_end(change)
elif result == 7:  
  renameObjectFromLinkedData(change)
elif result == 8:  
  list_names(change)

# only draw the rename count if something is being renamed
if renameCount > -1:
 Draw.PupMenu('renamed: %d objects.' % renameCount) 
 
Window.WaitCursor(0) 
 
main()



(ideasman42) #7

Hi, Im not exactly sure what your trying to do here-

but I noticed a bug.
if ob.name == ob.getData(): # Will never be true
shoud be…
if ob.name == ob.getData(1): # 1 == name_only

Listing object names might be bad since you can have 100’s of objects. why are you doing this?

  • Dont mean to put you off, I should probably read and compare your code to mine…
  • Cam

(zenoscope) #8

if ob.name == ob.getData(1): # 1 == name_only
this didn’t work for me (blender 2.36) it came up with an error, which was why i changed it. ob.getData() works for me, which is all i care about :slight_smile:

the list, i realise could be a bad idea (especially since its set to a max number of 20 rows but it only lists the objects that are selected. i could put in some code to make it send an error message when more than a certain number of objects are selected…

there is also a (rather major) bug in the data rename. If you have multiple objects selected that use the same datablock, and you try to rename the datablocks, you effectively rename each multiple times, and blender just names everything as meaningless numbers intead ie 1.002.
so you need to select only one object per datablock you want to rename.


(ideasman42) #9

getData(1) is 2.37+ only, why are you using 2.36?.


if ob.name == ob.getData(): # Will necver be true since ob.name is a string and an objects data will never be a string.

Replace with
if ob.name == ob.getData().name or…
if ob.name == ob.data.name.

But Id just use 2.37 if I where you.


(zenoscope) #10

i was using 2.36 coz i found the menus redraw really slowly :frowning:
But I’m used to it now…
I’ve been reading the python docs for 2.37 and rubbing my hands with evil glee, its amazing the new stuff they’ve put in there!


(edem) #11

hello blender heads :slight_smile:

with this cript is possible rename ME: datablock too? and i will be the same name as OB: datablock?