import bpy

def optimize_mesh_for_ogre(obj):
    if obj.type != 'MESH':
        return
    print(obj.type)

    print(f"Starting with {obj.name}")
    # Set as active and enter Weight Paint mode to use ops
    bpy.context.view_layer.objects.active = obj
    bpy.ops.object.mode_set(mode='WEIGHT_PAINT')

    # 1. Clean zero weights (below 0.001)
    bpy.ops.object.vertex_group_clean(group_select_mode='ALL', limit=0.001)

    # 2. Limit influences to 4 per vertex (Ogre/GPU standard)
    bpy.ops.object.vertex_group_limit_total(limit=4)

    # 3. Normalize all weights (Sum of all bone influences = 1.0)
    # This prevents "multiplied" or "weak" movements in engine
    bpy.ops.object.vertex_group_normalize_all()

    bpy.ops.object.mode_set(mode='OBJECT')

    # 4. Remove empty Vertex Groups (groups with no assigned vertices)
    # This keeps the bone index list identical across modular parts
    vgroup_indices_to_remove = []
    for i, group in enumerate(obj.vertex_groups):
        has_vertices = False
        for v in obj.data.vertices:
            for g in v.groups:
                if g.group == i and g.weight > 0.001:
                    has_vertices = True
                    break
            if has_vertices: break
        
        if not has_vertices:
            print("removed group:" + group.name)
            vgroup_indices_to_remove.append(group.name)

    for name in vgroup_indices_to_remove:
        print("removing group: " + name)
        obj.vertex_groups.remove(obj.vertex_groups.get(name))
    
    print(f"Finished {obj.name}: 4-weight limit applied, Normalized, {len(vgroup_indices_to_remove)} empty groups removed.")

# Execute on all selected mesh objects
selected_meshes = [o for o in bpy.data.objects if o.type == 'MESH' and not o.name.startswith("cs_")]
if not selected_meshes:
    print("No mesh objects selected.")
else:
    for mesh_obj in selected_meshes:
        optimize_mesh_for_ogre(mesh_obj)

