import bpy from bpy.props import FloatProperty from bpy.types import Context, Operator, Panel class ArmEditOperator: @classmethod def poll(cls, context: Context): return ( context.active_object and context.active_object.type == 'ARMATURE' and context.active_bone and context.mode == 'EDIT_ARMATURE' ) class ARMATURE_OT_ReadBoneLength(ArmEditOperator, Operator): """Make length property equal to actual bone length""" bl_idname = "armature.read_bone_length" bl_label = "Read Bone Length" bl_options = {'UNDO'} def execute(self, context): context.active_bone.bbone_y = context.active_bone.length return {'FINISHED'} class ARMATURE_OT_MakeBoneSquare(ArmEditOperator, Operator): """Make bone's width and depth equal to it's length""" bl_idname = "armature.make_bone_square" bl_label = "Make Bone Square" bl_options = {'UNDO'} def execute(self, context): context.active_bone.bbone_x = context.active_bone.bbone_z = context.active_bone.length * 0.5 return {'FINISHED'} class VIEW3D_PT_bone_size(Panel): bl_space_type = 'VIEW_3D' bl_region_type = 'UI' bl_label = "Bone Size" bl_options = {'DEFAULT_CLOSED'} @classmethod def poll(cls, context: Context): scene = context.space_data ob = context.active_object return scene and ob and ob.type == 'ARMATURE' and ob.mode == 'EDIT' def draw(self, context: Context): layout = self.layout col = layout.column() col.prop(context.active_bone, "bbone_x", text="Bone Width") col.prop(context.active_bone, "bbone_z", text="Bone Depth") sub = col.row(align=True) sub.operator(ARMATURE_OT_ReadBoneLength.bl_idname, icon="COPYDOWN", text="") sub.prop(context.active_bone, "bbone_y", text="Bone Length") col.operator(ARMATURE_OT_MakeBoneSquare.bl_idname, icon="MESH_PLANE") def update_length(self, context) -> None: context.active_bone.length = self.bbone_y def register(): bpy.types.EditBone.bbone_y = FloatProperty( name="B-Bone Display Y Length", description="B-Bone Y size", default=1.0, min=0.0, soft_min=0.001, step=10, precision=3, options={'HIDDEN'}, update=update_length, ) bpy.utils.register_class(ARMATURE_OT_ReadBoneLength) bpy.utils.register_class(ARMATURE_OT_MakeBoneSquare) bpy.utils.register_class(VIEW3D_PT_bone_size) def unregister(): bpy.utils.unregister_class(VIEW3D_PT_bone_size) bpy.utils.unregister_class(ARMATURE_OT_MakeBoneSquare) bpy.utils.unregister_class(ARMATURE_OT_ReadBoneLength) del bpy.types.EditBone.bbone_y register()