Created
May 12, 2021 13:45
-
-
Save FreshlyBrewedCode/26327e26b976b2a0fc886779ec11f542 to your computer and use it in GitHub Desktop.
Blender Auto Rig Hierarchy Operator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import bpy | |
from mathutils import Vector, Matrix | |
#Create the armature | |
def create_armature(object, collection): | |
armature_data = bpy.data.armatures.new(object.name) | |
armature = bpy.data.objects.new(object.name, armature_data) | |
armature.matrix_basis = object.matrix_basis | |
collection.objects.link(armature) | |
return armature | |
#Create the bones | |
def bone_from_hierarchy(object, armature, parent_bone = None): | |
#Create a bone parented and disconnect to its parent | |
bone = armature.data.edit_bones.new(object.name) | |
bone.parent = parent_bone | |
bone.use_connect = False | |
#Get its transformation matrix inside the armature from the object matrix | |
matrix = armature.matrix_world.inverted() @ object.matrix_world | |
#Place head and tail | |
bone.head = matrix @ Vector() | |
bone.tail = matrix @ Vector((0.0, 0.0, 1.0)) | |
if 'stop_rig' in object.keys(): | |
return | |
#Recurse through the children objects | |
for child in object.children: | |
bone_from_hierarchy(child, armature, bone) | |
#Parent the objects to the armarture | |
def parent_from_hierarchy(object, armature): | |
name = object.name | |
#Get the pose bone | |
bone = armature.pose.bones[name] | |
#Keep the object position | |
matrix_world = object.matrix_world.copy() | |
#Parent it | |
object.parent = armature | |
object.parent_type = 'BONE' | |
object.parent_bone = name | |
#Make so we can unparent and keep object's position | |
bone_matrix = Matrix.Translation(bone.tail - bone.head) @ bone.matrix | |
object.matrix_parent_inverse = (armature.matrix_world @ bone_matrix).inverted() | |
#Assigns its position | |
object.matrix_world = matrix_world | |
if 'stop_rig' in object.keys(): | |
return | |
#Recurse through the children | |
for child in object.children: | |
parent_from_hierarchy(child, armature) | |
def make_bone_hierarchy(object): | |
if object: | |
armature = create_armature(object, object.users_collection[0]) | |
#Enter edit mode for the armature in order to create edit bones | |
bpy.context.view_layer.objects.active = armature | |
bpy.ops.object.mode_set(mode='EDIT') | |
bone_from_hierarchy(object, armature) | |
#Back to object mode | |
bpy.ops.object.mode_set(mode='OBJECT') | |
#bpy.context.view_layer.objects.active = object | |
#Parent the objects to the armature | |
parent_from_hierarchy(object, armature) | |
def main(context): | |
root = context.active_object | |
make_bone_hierarchy(root) | |
class SimpleOperator(bpy.types.Operator): | |
"""Tooltip""" | |
bl_idname = "object.auto_rig_hierarchy" | |
bl_label = "Auto Rig Hierarchy" | |
@classmethod | |
def poll(cls, context): | |
return context.active_object is not None | |
def execute(self, context): | |
main(context) | |
return {'FINISHED'} | |
def register(): | |
bpy.utils.register_class(SimpleOperator) | |
def unregister(): | |
bpy.utils.unregister_class(SimpleOperator) | |
if __name__ == "__main__": | |
register() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment