A simple tool which uses regular expressions to rename many bones or objects at once.

I am not an experienced programmer. But I wrote a script which uses Regular Expressions to rename many objects or bones.
You can find the User Interface on the Tool shelf. It works in Object Mode and in Armature Edit Mode.

For example, if you are rigging and you are fed up renaming bones one by one (Adding prefixes like DEF_ or MCH_ ), you might want to give Regular Expressions a try. Let the computer do the work for you.


import re

import bpy
from bpy.props import *

class RE_Tool_PropertyGroup(bpy.types.PropertyGroup):
    simple_op_prefix = StringProperty(name="Simple Operator Prefix", default="My Prefix")
    regex_sel = StringProperty(name="Regexp Select", default=r".*")
    regex_src = StringProperty(name="Regexp Src", default=r"(.*)")
    regex_repl = StringProperty(name="Regexp Repl", default=r"\1")


class RE_Tool_Object(bpy.types.Panel):
    bl_label = "Regular Expression Tool"
    bl_space_type = "VIEW_3D"
    bl_region_type = "TOOLS"
    bl_context = "objectmode"

    def draw(self, context):
        layout = self.layout
        sce = context.scene
        
        
        obj = context.object
        
        # init argument
        
        row = layout.row()
        row.label("Selecting Objects")

        row = layout.row()        
        row.prop(sce.retoolproperties, "regex_sel", text="")
        row.operator("object.regex_select")
        row = layout.row()        
        row.separator()

        #  
        row = layout.row()
        row.label("Renaming Objects")

        row = layout.row()
        row.prop(sce.retoolproperties, "regex_src", text="")
        row.prop(sce.retoolproperties, "regex_repl", text="")
        row = layout.row()        
        row.operator("object.regex_rename")

class RE_Tool_Armature(bpy.types.Panel):
    bl_label = "Regular Expression Tool"
    bl_space_type = "VIEW_3D"
    bl_region_type = "TOOLS"
    bl_context = "armature_edit"

    def draw(self, context):
        layout = self.layout
        sce = context.scene
        
        
        obj = context.object
        
        # init argument
        
        row = layout.row()
        row.label("Selecting Bones")

        row = layout.row()        
        row.prop(sce.retoolproperties, "regex_sel", text="")
        row.operator("object.regex_select")
        row = layout.row()        
        row.separator()

        #  
        row = layout.row()
        row.label("Renaming Bones")

        row = layout.row()
        row.prop(sce.retoolproperties, "regex_src", text="")
        row.prop(sce.retoolproperties, "regex_repl", text="")
        row = layout.row()        
        row.operator("object.regex_rename")
        
# ---
# ---
# ---

class RenameOperator(bpy.types.Operator):
    ''''''
    bl_idname = "object.regex_rename"
    bl_label = "Rename"
    
    #    bpy.types.Scene.retoolproperties.simple_op_prefix = StringProperty(name="Simple Operator Prefix", default="My Prefix")

    @classmethod
    def poll(cls, context):
        return context.active_object != None

    def execute(self, context):
        sce = context.scene
        re_src=sce.retoolproperties.regex_src
        re_repl=sce.retoolproperties.regex_repl
        
        if (bpy.context.mode == 'EDIT_ARMATURE'):  
            for b in context.selected_editable_bones:
                b.name = re.sub(re_src, re_repl, b.name)
     
        elif (bpy.context.mode == 'OBJECT'):
            for o in context.selected_editable_objects:
                o.name = re.sub(re_src, re_repl, o.name)

        return {'FINISHED'}

# ---
# ---
# ---
  
def select_regexp_bones(context, reg):
  arm_obj = context.active_object
  arm=arm_obj.data
  reg_exp = re.compile (reg)
  for b in arm.edit_bones:
    if reg_exp.match(b.name):
      b.select = True
      b.select_head = True
      b.select_tail = True

def select_regexp_objects(context, reg):
  reg_exp = re.compile (reg)
  for o in  context.visible_objects:
    if reg_exp.match(o.name):
      o.select = True

   
class RegexpSelect(bpy.types.Operator):
    ''''''
    bl_idname = "object.regex_select"
    bl_label = "Select"
    
    @classmethod
    def poll(cls, context):
        return context.active_object != None

    def execute(self, context):
        print(bpy.context.mode)
        sce = context.scene
        re_sel=sce.retoolproperties.regex_sel
        if (bpy.context.mode == 'EDIT_ARMATURE'):       
            select_regexp_bones(context, re_sel)
        elif (bpy.context.mode == 'OBJECT'):
            select_regexp_objects(context, re_sel)
        return {'FINISHED'}
 
def register():
    bpy.utils.register_class(RE_Tool_PropertyGroup)
    bpy.types.Scene.retoolproperties = bpy.props.PointerProperty( type = RE_Tool_PropertyGroup )
    
    bpy.utils.register_class(RenameOperator)
    bpy.utils.register_class(RegexpSelect)

    bpy.utils.register_class(RE_Tool_Armature)
    bpy.utils.register_class(RE_Tool_Object)

def unregister():
    bpy.utils.unregister_class(RE_Tool_Armature)
    bpy.utils.unregister_class(RE_Tool_Object)

    bpy.utils.unregister_class(RenameOperator)
    bpy.utils.unregister_class(RegexpSelect)
    bpy.utils.unregister_class(RE_Tool_PropertyGroup)



if __name__ == "__main__":
    register()

Hi Proxe.

Your module does something similar. Thats the type of module I am looking for!

It does not depend on the mode (Armature Edit, Object Mode, etc).
I tried some similar tasks with it. It worked. Regex Replace worked, too!

Regular expressions ‘replace’ is more general. Trimming, and adding/removing prefixes or suffixes, all can be done with it.

 "search for" -> "replace by"

# A Prefix in Regex 
"^"  --> "MyPrefix_"

# A Postfix in Regex 
"$" -> "_MyPostfix"

# Trim first 3 
"^..." -> ""

# Another Trim. Remove all occourences of "substring"
"substring" -> ""

# Trim ... skip first 3 and last 3
"^.{3}(.*).{3}$ -> "\1"

# Trim ... skip first 3, collect 4 characters, skip the rest. Similar to "trim from 3 to 7"
"^.{3}(.{4}).*$" -> "\1"

With Regular Expressions, there is no need for extra functions like Trim or Suffix. But the end user has to know how to use Regular Expressions. That is a disadvantage, it might result in Regular Expressions being ignored.

An idea …

In the naming, maybe it would be an idea to have some standard strings like
: obj : (for object, e.g. in Armature Edit Mode)
: grp : (Object Group)
: scn : (for scene)
If there is ": obj : " in the replacement_string or the name string, the name of the active object would be put in place.

E.G.
“: obj :_Chrome_Material” -> “MyObject_Chrome_Material”

They can be combined …
“: scn :: grp :: obj :_MyMaterial” -> “Scene1_AnObjectGrp_MyObject_MyMaterial”
and used in renamings.
What do you think about it?

Thank you for your awareness.

Happy blending!

Hi Proxe.

Your module does something similar. Thats the type of module I am looking for!

It does not depend on the mode (Armature Edit, Object Mode, etc).
I tried some similar tasks with it. Iit worked. Regex Replace worked, too!

Regular expressions ‘replace’ is more general. Trimming, and adding/removing prefixes or suffixes, all can be done with it.

 
<search for> -> <replace by>
# A Prefix in Regex 
"^"  --> "MyPrefix_"

# A Postfix in Regex 
"$" -> "_MyPostfix"

# Trim first 3 
"^..." -> ""

# Another Trim. Remove all occourences of "substring"
"substring" -> ""

# Trim ... skip first 3 and last 3
"^.{3}(.*).{3}$ -> "\1"

# Trim ... skip first 3, collect 4 characters, skip the rest. Similar to "trim from 3 to 7"
"^.{3}(.{4}).*$" -> "\1"

With Regular Expressions, there is no need for extra functions like Trim or Suffix. But the end user has to know how to use Regular Expressions. That is a disadvantage, it might result in Regular Expressions being ignored.

An idea I like to mention.

In the naming, maybe it would be an idea to have some standard strings like
: obj : (for object, e.g. in Armature Edit Mode)
: grp : (Object Group)
: scn : (for scene)
If there is ": obj : " in the replacement_string or the name string, the name of the active object would be put in place.

E.G.
“: obj :_Chrome_Material” -> “MyObject_Chrome_Material”

What do you think about it?

Thank you for your awareness.

Happy blending!

I like the idea, I was planning on implementing two rows, where one was the source and the other was the destination for copying names, this could, in the background, send the same values as those that would be used in the name field for copying.

On regular expressions, although they are supported, the add-on doesn’t revolve around them, making them less obvious, I expect that the average user would not use regular expressions, likely because they would not know how to, even though it is the more powerful option.

Currently the add-on is in its infancy, relying on context, although via selection and written in a ‘bug testing’ format, version 1.0 will more properly formatted and access/modify via bpy.data, for concept and testing it is faster to use context, but with a bpy.data structure there will be options to rename everything within the scene or across the scenes, further increasing usability.

Edit - Not sure why I said only the find field supports re’s I used re.sub, just as you did in your script.

Making most people use regular expressions, to make it a core util, to build most around it. Thats the direction I would follow. To ‘make’ people use them. In my opinion, regular expressions should not be something ‘beside’ for hackers.

Helpers (like Trim, Prefix,Postfix) could be used. But, instead of performing direct renames those helpers can generate regular expressions a user can read. To keep the user in touch with regular expressions. If he does not like to use them, he can still use the helpers.

I like the Idea with the two windows (1 - objects chosen for renaming;; 2 - what they would be after renaming). It would be a play-ground to experiment (non-destructive) with regular expressions, it will be very important to help to gasp its concept. If many objects across the scenes have to be renamed, it also gives us a feedback which ones will be renamed. It will prevent us from renaming objects accidently.
A very nice feature!

( ~~~ )

I play around with Blenders Outliner. I believe it could be useful for annoying repetive tasks (like our renaming).
Searched around in INet, I have problems to find a source which explains what bl_context/bl_region_type/bl_space_type combinations are possible with the Outliner.
I wrote a little header class which outputs something into the header of the Outliner. I also can embed a panel into an operator, which only works if you call it from the Outliner.

But I do not have an idea how to add a panel to the Outliner directly. (Looking for something like a Tool Shelf for the Outliner)