def set_parent(blender_object:bpy.types.Object,parent_info:ParentInfo)->None: assert isinstance(blender_object,bpy.types.Object) blender_object.parent = parent_info.parent blender_object.parent_type = parent_info.parent_type if parent_info.parent_type == _BONE: assert parent_info.parent.type == _ARMATURE and\ parent_info.parent.data.bones.get(parent_info.parent_bone) is not None blender_object.parent_bone = parent_info.parent_bone
def build_pyramid_bones(armature_object: bpy.types.Object, pyramid_mesh_object: bpy.types.Object, target_bone_name: str, parent_bone_name: str): bone_names = PyramidBoneNames(target_bone_name) armature: bpy.types.Armature = armature_object.data if bone_names.base in armature.bones: # already built return print(f'build pyramid bones: {target_bone_name}') bpy.context.selected_objects.append(armature_object) bpy.context.view_layer.objects.active = armature_object bpy.ops.object.mode_set(mode='EDIT') pyramid_mesh: bpy.types.Mesh = pyramid_mesh_object.data vertices: List[Vector] = [v.co for v in pyramid_mesh.vertices] origin: Vector = pyramid_mesh_object.location - armature_object.location direction: Vector = vertices[PyramidVertex.APEX].normalized() bone_length = vertices[PyramidVertex.APEX].length / 7.5 bone_vector = direction * bone_length # Move the apex vertex into the mesh pyramid_mesh.vertices[PyramidVertex.APEX].co -= bone_vector pyramid_mesh.update() def create_bones(): base_bone = armature.edit_bones.new(bone_names.base) base_bone.head = origin base_bone.tail = origin + bone_vector base_bone.parent = armature.edit_bones[parent_bone_name] apex_bone = armature.edit_bones.new(bone_names.apex) apex_bone.parent = base_bone apex_bone.head = origin + vertices[PyramidVertex.APEX] apex_bone.tail = origin + vertices[PyramidVertex.APEX] + bone_vector base_a_bone = armature.edit_bones.new(bone_names.base_a) base_a_bone.parent = base_bone base_a_bone.head = origin + vertices[PyramidVertex.BASE_A] base_a_bone.tail = origin + vertices[PyramidVertex.BASE_A] + bone_vector base_b_bone = armature.edit_bones.new(bone_names.base_b) base_b_bone.parent = base_bone base_b_bone.head = origin + vertices[PyramidVertex.BASE_B] base_b_bone.tail = origin + vertices[PyramidVertex.BASE_B] + bone_vector base_c_bone = armature.edit_bones.new(bone_names.base_c) base_c_bone.parent = base_bone base_c_bone.head = origin + vertices[PyramidVertex.BASE_C] base_c_bone.tail = origin + vertices[PyramidVertex.BASE_C] + bone_vector base_d_bone = armature.edit_bones.new(bone_names.base_d) base_d_bone.parent = base_bone base_d_bone.head = origin + vertices[PyramidVertex.BASE_D] base_d_bone.tail = origin + vertices[PyramidVertex.BASE_D] + bone_vector create_bones() bpy.ops.object.mode_set(mode='OBJECT') pyramid_mesh_object.parent = armature_object pyramid_mesh_object.parent_type = 'BONE' pyramid_mesh_object.parent_bone = bone_names.base pyramid_mesh_object.matrix_parent_inverse = armature.bones[bone_names.base].matrix_local.inverted() @ Matrix.Translation(-bone_vector) bpy.ops.object.mode_set(mode='POSE') armature_editor = ArmatureEditor(armature_object) pose_bones = armature_editor.pose_bones armature_editor.add_copy_location_constraint(pose_bones[bone_names.apex], pyramid_mesh_object, 'apex', 'WORLD') armature_editor.add_copy_location_constraint(pose_bones[bone_names.base_a], pyramid_mesh_object, 'base_a', 'WORLD') armature_editor.add_copy_location_constraint(pose_bones[bone_names.base_b], pyramid_mesh_object, 'base_b', 'WORLD') armature_editor.add_copy_location_constraint(pose_bones[bone_names.base_c], pyramid_mesh_object, 'base_c', 'WORLD') armature_editor.add_copy_location_constraint(pose_bones[bone_names.base_d], pyramid_mesh_object, 'base_d', 'WORLD') bones = armature_editor.bones bones[bone_names.base].use_deform = False bones[target_bone_name].use_deform = False bpy.ops.object.mode_set(mode='OBJECT')