import bpy from mathutils import Matrix, Vector def get_bone_size_factor(bone, ob, relative=True): world_box = [ob.matrix_world @ Vector(co) for co in ob.bound_box] height = (world_box[1]-world_box[0]).length depth = (world_box[3]-world_box[0]).length width = (world_box[4]-world_box[0]).length ''' length = height if height < 0.001: if depth > 0.001: length = depth elif width > 0.001: length = width ''' length = max((height, depth, width)) size_factor = 1 / length if relative: size_factor /= bone.bone.length return size_factor def transform_matrix(loc=(0, 0, 0), rot=(0, 0, 0), scale=(1, 1, 1)): l_mat = Matrix.Translation(Vector(loc)) rx_mat = Matrix.Rotation(rot[0], 4, 'X') ry_mat = Matrix.Rotation(rot[1], 4, 'Y') rz_mat =Matrix.Rotation(rot[2], 4, 'Z') r_mat = rz_mat @ ry_mat @ rx_mat sx_mat = Matrix.Scale(scale[0], 4, Vector((1,0,0))) sy_mat = Matrix.Scale(scale[1], 4, Vector((0,1,0))) sz_mat = Matrix.Scale(scale[2], 4, Vector((0,0,1))) s_mat = sx_mat @ sy_mat @ sz_mat return l_mat @ r_mat @ s_mat def get_bone_matrix(bone): bone_mat = bone.matrix if bone.custom_shape_transform: bone_mat = bone.custom_shape_transform.matrix bone_mat = bone_mat @ transform_matrix(scale=(bone.bone.length,)*3) bone_mat = bone.id_data.matrix_world @ bone_mat return bone_mat def apply_mat_to_verts(data, mat, coords=None): if coords is None: coords = [v.co for v in data.vertices] coords = [v for co in coords for v in mat @ co] data.vertices.foreach_set('co', coords) data.update() def transform_mesh(data, loc, rot, scale, xz_scale, size, slide, coords=None): if coords is None: coords = [0]*len(data.vertices)*3 data.vertices.foreach_get('co', coords) sx = scale[0] * size * xz_scale sy = scale[1] * size sz = scale[2] * size * xz_scale l_vec = loc + Vector((0, slide, 0)) mat = transform_matrix(l_vec, rot, (sx, sy, sz)) data.vertices.foreach_set('co', coords) data.transform(mat) #apply_mat_to_verts(data, mat, coords)