Parent Object to Nearest Bone addon (free) [Updated dec 19 2022]

[ Update 19 dec 2022:
Now the parenting is made comparing the bone’s center with the geometrical center of the objects, instead of the bone’s head vs object origin. This solves many problems of the former method, when more than one bone share the same head position. I changed the text below to reflect this.]

Hi!
I made this very simple addon to aid in mechanical rigging:
Parent Object to Nearest Bone.
It works like this. Suppose you are to rig a robot made of many rigid and undeforming parts, each a separate object.
The best way to rig this would be to parent each object to a different bone in your armature, but you will have to:

  • select one bone in pose mode.
  • switch to object mode
  • deselect
  • select the object to parent
  • shift select the Armature
  • hit Ctl+P (Parent menu) and choose “Bone”
  • repeat all of the above for each object and bone to parent

This is very time consuming.
With this addon you can:

  • Select ALL your objects at once (using lasso, for example)
  • shift select the armature to make it active object
  • Goto the menu Object–>Parent–>Parent to nearest Bone
    And voilá, the script parents each object to the nearest available bone in your Armature :slight_smile:

Notes:

  • The script compares the geometric center of the object (not the origin or the pivot point) with the center of the bone. This worked flawlessly on all the tests I did. If you find an issue, please tell me.
  • The operator is in the Object–>Parent menu, I couldn’t find a way to make it appear in the CTL+P menu. If you know how to do it, and want to help, please tell me :slight_smile:

This is available for free on Github:
https://github.com/g3ntile/parentToNearestBone

I hope this ends up being useful to you.

This addon was inspired in a request by the awesome Polyfjord in this tutorial. Go watch his stuff, he’s a wonderful artist.

DISCLAIMER: I’m not a developer, just a user with limited scripting skills. This may have errors, or stuff not done properly. If you have an idea to improve it please tell me.

9 Likes

I’m releasing a new version. Now the detection is being done using the bone center instead of the head, to avoid the “bones sharing head” problem, and the geometric center of the object, instead of the Origin. I’ll upload it soon and update this post accordingly.

4 Likes

I love all ideas that automate boring repetitive work. Thank you :slight_smile:

2 Likes

We definitively need a video. This reads cool news. :slight_smile:

1 Like

Dude. I hope Polyfjord has seen and recognized this marvelous contribution you’ve made. Super helpful, what a breeze to use. Thanks a bunch!

1 Like

Yep, I’ll revive this to ask an entitled, needy question…

Is there a way this could be added to the Ctrl-P menu? Is that a thing that can be done?

import bpy

# Define the custom menu class
class OBJECT_MT_custom_parent_set_menu(bpy.types.Menu):
    bl_label = "Custom Parent Set Menu"
    bl_idname = "OBJECT_MT_custom_parent_set_menu"

    def draw(self, context):
        layout = self.layout
        # Add Hello World label
        layout.label(text="Hello World")
        # Add "object.parent_set" operator to the menu
        layout.operator_enum("object.parent_set", "type")

# Define the operator to show the menu via a shortcut
class OBJECT_OT_show_custom_menu(bpy.types.Operator):
    bl_idname = "object.show_custom_menu"
    bl_label = "Show Custom Menu"

    def execute(self, context):
        bpy.ops.wm.call_menu(name=OBJECT_MT_custom_parent_set_menu.bl_idname)
        return {'FINISHED'}

# Register the operator and menu
def register():
    bpy.utils.register_class(OBJECT_MT_custom_parent_set_menu)
    bpy.utils.register_class(OBJECT_OT_show_custom_menu)
    # Add shortcut to keymap
    wm = bpy.context.window_manager
    km = wm.keyconfigs.addon.keymaps.new(name="Object Mode", space_type="EMPTY")
    kmi = km.keymap_items.new("object.show_custom_menu", 'P', 'PRESS', ctrl=True)

def unregister():
    bpy.utils.unregister_class(OBJECT_MT_custom_parent_set_menu)
    bpy.utils.unregister_class(OBJECT_OT_show_custom_menu)
    # Remove the shortcut from keymap
    wm = bpy.context.window_manager
    km = wm.keyconfigs.addon.keymaps.get("Object Mode")
    if km:
        for kmi in km.keymap_items:
            if kmi.idname == "object.show_custom_menu":
                km.keymap_items.remove(kmi)
                break

if __name__ == "__main__":
    register()

Does this method work?

This is a way to create a new CTRL+P operator menu and override it.


On second thought, it would have been simpler to call Menu directly…


import bpy

# Define the custom menu class
class OBJECT_MT_custom_parent_set_menu(bpy.types.Menu):
    bl_label = "Custom Parent Set Menu"
    bl_idname = "OBJECT_MT_custom_parent_set_menu"

    def draw(self, context):
        layout = self.layout
        # Add Hello World label
        layout.label(text="Hello World")
        # Add "object.parent_set" operator to the menu
        layout.operator_enum("object.parent_set", "type")

# Register the menu and add the shortcut to the keymap
def register():
    bpy.utils.register_class(OBJECT_MT_custom_parent_set_menu)
    # Add shortcut to keymap
    wm = bpy.context.window_manager
    km = wm.keyconfigs.addon.keymaps.new(name="Object Mode", space_type="EMPTY")
    kmi = km.keymap_items.new("wm.call_menu", 'P', 'PRESS', ctrl=True)
    kmi.properties.name = "OBJECT_MT_custom_parent_set_menu"

def unregister():
    bpy.utils.unregister_class(OBJECT_MT_custom_parent_set_menu)
    # Remove the shortcut from keymap
    wm = bpy.context.window_manager
    km = wm.keyconfigs.addon.keymaps.get("Object Mode")
    if km:
        for kmi in km.keymap_items:
            if kmi.idname == "wm.call_menu" and kmi.properties.name == "OBJECT_MT_custom_parent_set_menu":
                km.keymap_items.remove(kmi)
                break

if __name__ == "__main__":
    register()

If you want to add an item in front of the menu
bpy.types.VIEW3D_MT_object_parent.prepend
to see if it works.