#!BPY """ # Name: 'RegexpRenameSelectedObject' # Blender: 237 # Group: 'Object' # Tip: 'REGXP rename selected objects' """ __author__ = 'Cram TeXeD' __version__ = '1.0 2005/11/11' __email__ = [ 'Cram TeXeD', 'marclan@free.fr' ] # # This script renames object, bones or vertex group by substituing # part of their name matching regular expression by a string. # # It's my first Python script so there could be some odd stuff # or much pretty trick to do. Be kind, mail me if you notice such a thing # to improve this script. # Next improvements should be : # - Allows group search and replace # - Save and open preference and most-used request. # - Extend to other object such as Lamp, Face, etc... # import Blender import re from Blender import Object, Draw, BGL, Scene, Armature, NMesh, Window from Blender.Armature import Bone # Events ID evtPattern = 0 evtRepl = 1 evtDisplayList = 2 evtExit = 3 evtType = 4 # Button patternButton = Draw.Create("Bone") replButton = Draw.Create("new") doButton = "" exitButton = "" typeMenu = Draw.Create(1) typeKind = 'Object' # Global message storage. message = "" activeObject = None # Class for data storage class DataList : def __init__(self,datalist = []) : self.list = datalist self.type = 'Object' def append(self, object) : self.list.append(object) def clear(self) : print "CLEAR" self.list[:] = [] type = None print self.list def size(self) : return len(self.list) # User defined Exception class MyError(Exception) : def __init__(self, message) : self.message = message def __str__(self) : return str(self.message) # GUI Definition def gui() : global evtPattern, evtRepl, evtDisplayList, evtExit, evtType global patternButton, replButton, typeMenu global message ## - WARNING - BGL ref. starts from bottom ! BGL.glRasterPos2i(10,70) Draw.Text(message) BGL.glRasterPos2i(10,100) Draw.Text("You can type Q or ESC to Quit") exitButton = Draw.Button("Exit", evtExit, \ 10, 130, 160, 18, "Exit" ) doButton = Draw.Button("See", evtDisplayList, \ 10, 160, 160, 18, "Display the change list BUT DOESN'T act before you confirm !") replButton = Draw.String("New String : ", evtRepl, \ 10, 190, 240, 18, replButton.val \ , 20, "The String value to replace matched parts.") patternButton = Draw.String("Regexp : ", evtPattern, \ 10, 220, 240, 18, patternButton.val \ , 20, "Regular expression (see module 're' documentation).") typeMenu = Draw.Menu("Type %t | Selected Objects %x1 | Active Object Bones %x2 | Active Object VertexGroups %x3", evtType, \ 260, 220, 180, 18, typeMenu.val, \ "Choice target") BGL.glRasterPos2i(10,270) Draw.Text("All steps need confirmation, so be cool :)") BGL.glRasterPos2i(25,290) Draw.Text("object.name != re.sub( pattern, object.name)") BGL.glRasterPos2i(10,310) Draw.Text("Rename only SELECTED objects with following condition") def event(evt, val): """keyboard and mouse events Handler""" if evt == Draw.ESCKEY or evt == Draw.QKEY: doExit() def doExit(): """Does exit""" stop = Draw.PupMenu("OK?%t|Exit %x1") if stop == 1: Draw.Exit() return def buttonEvt(evt): """Button Event Handler""" global evtPattern, evtRepl, evtDisplayList, patternButton, replButton, evtExit, typeMenu, evtType, typeKind global message message = "" if evt == evtDisplayList : try : datalist = doList( patternButton.val, replButton.val) print "DATALIST %s" % datalist.list nb = datalist.size() # Test : if there's any matching object, rename them # else print kindly message. if nb > 0 : tabList = [ "%s : %s -> %s" % (getName(t),u,v) for (u,v,t) in datalist.list ] name = "Changes to do%t |"+ \ " |".join( tabList )+ \ " | %l | Confirm %x9999 | Cancel %x8888 " if Draw.PupMenu(name) == 9999 : doRename(datalist) Draw.Draw() else : datalist.clear() else : message = "No matching object" Draw.PupMenu( message+"%t| Ok %x1") Draw.Draw() except MyError, val : print val message = val.message Draw.PupMenu("Error%t|"+val.message) Draw.Draw() elif evt == evtExit : doExit() Draw.Register(gui, event, buttonEvt) def getName(object) : if hasattr(object, "getData") : return str( type ( object.getData())) else : return str(type(object)) def doList(patternVal, replVal) : """Creates matching object list""" global activeObject, typeMenu if ( patternButton is None or replVal is None) : raise MyError ("Pattern or replacement is None") try : regCmp = re.compile(patternVal) except Exception, e : raise MyError("Regexp Error : "+str(e)) subjectlist = [] # Identify target if typeMenu.val == 1 : typeKind = 'Object' elif typeMenu.val == 2 : typeKind = 'Bones' elif typeMenu.val == 3 : typeKind = 'VertexGroup' else : typeKind = 'Object' print "TypeKind %s typeMenu %s " % (typeKind, typeMenu.val) if typeKind == 'Object' : subjectlist = Object.GetSelected() retList = doListGeneral(regCmp, replVal, subjectlist) else : sc = Scene.GetCurrent() # sc.update() activeObject = sc.getActiveObject() # If no active object if activeObject is None : raise MyError("No active object. Please select one.") # # - Bones - # if typeKind == 'Bones' and activeObject.getType() == 'Armature' : subjectlist = activeObject.getData().getBones() retList = doListGeneral(regCmp, replVal, subjectlist) # # - Vert Group # elif typeKind == 'VertexGroup' : mesh = activeObject.getData() if not hasattr(mesh,'getVertGroupNames') : raise MyError("Is not a Mesh") subjectlist = mesh.getVertGroupNames() retList = doListVertGroup(regCmp, replVal, subjectlist, mesh) else : raise MyError(str(type(activeObject))+" doesn't match with requirements "+typeKind) retList.type = typeKind return retList def doListGeneral(regCmp, replVal, subjectlist) : nb =len( subjectlist) print subjectlist if nb == 0 : raise MyError("No Selected Object. You must select someones.") retList = DataList() for o in subjectlist : print regCmp newName = regCmp.sub(replVal, o.name) if newName != o.name : retList.append( (o.name, newName, o) ) return retList def doListVertGroup(regCmp, replVal, subjectlist, mesh) : nb = len(subjectlist) print subjectlist if nb == 0 : raise MyError("No Selected Object. You must select someones.") retList = DataList() for name in subjectlist : newName = regCmp.sub(replVal, name) if newName != name : retList.append( (name, newName, mesh) ) return retList def doRename(datalist, typeKind = 'Object') : global message """ Renames object with object list """ if datalist.size() == 0 : return confirm = Draw.PupMenu("Confirm ? %t|Ok %x1 | Cancel %x2") if confirm == 1 : editmode = 0 try : editmode = Blender.Window.EditMode() if editmode : Blender.Window.EditMode(0) if datalist.type == 'Object' : renameObject(datalist) elif datalist.type == 'Bones' : renameBones(datalist) elif datalist.type == 'VertexGroup' : renameVertGroup(datalist) Blender.Redraw() message = "%s objects renamed" % ( datalist.size(), ) Draw.Draw() datalist.clear() finally : if editmode : Blender.Window.EditMode(1) Blender.Window.RedrawAll() print datalist.list return def renameObject(datalist) : for ( u, v, o ) in datalist.list : o.setName(v) def renameBones(datalist) : for ( u, v , o) in datalist.list : o.setName(v) def renameVertGroup(datalist) : for ( u,v,mesh ) in datalist.list : mesh.renameVertGroup(u,v) mesh.update()