import bpy
import bmesh

# Имена mesh и арматуры
mesh_name = "arm"
armature_name = "Reference"

# Находим объект mesh по имени
mesh_obj = bpy.data.objects.get(mesh_name)

# Находим объект арматуры по имени
armature_obj = bpy.data.objects.get(armature_name)

# Устанавливаем текущий кадр на 0
bpy.context.scene.frame_set(0)

# Принудительно обновляем сцену, чтобы применить анимацию
bpy.context.view_layer.update()

# Открываем файл для записи
with open("C:\\Work\\Projects\\witcher001\\resources\\w\\zombie002.txt", "w") as file:
    # Обработка арматуры и анимации
    if armature_obj and armature_obj.type == 'ARMATURE':
        file.write("=== Armature Matrix ===\n")
        for row in armature_obj.matrix_world:
            file.write(f"{row}\n")
        file.write(f"=== Armature Bones: {len(armature_obj.data.bones)}\n")
        for bone in armature_obj.data.bones:
            # Записываем имя кости, длину и связи
            file.write(f"Bone: {bone.name}\n")
            file.write(f"  HEAD_LOCAL: {bone.head_local}\n")
            file.write(f"  TAIL_LOCAL: {bone.tail_local}\n")
            file.write(f"  Length: {(bone.tail_local - bone.head_local).length}\n")
            for row in bone.matrix:
                file.write(f"    {row}\n")
            file.write(f"  Parent: {bone.parent.name if bone.parent else 'None'}\n")
            file.write(f"  Children: {[child.name for child in bone.children]}\n")
            
    # Обработка mesh
    if mesh_obj and mesh_obj.type == 'MESH':
        # Создаем копию mesh, чтобы не изменять оригинал
        mesh_copy = mesh_obj.copy()
        mesh_copy.data = mesh_obj.data.copy()
        bpy.context.collection.objects.link(mesh_copy)
        
        # Убедимся, что объект активен
        bpy.context.view_layer.objects.active = mesh_copy
        mesh_copy.select_set(True)
        
        # Применяем модификатор Armature (если он есть)
        for modifier in mesh_copy.modifiers:
            if modifier.type == 'ARMATURE':
                # Включаем модификатор, если он отключен
                if not modifier.show_viewport:
                    modifier.show_viewport = True
                if not modifier.show_render:
                    modifier.show_render = True
                
                # Проверяем, что модификатор связан с арматурой
                if modifier.object is None:
                    print(f"Модификатор Armature на объекте {mesh_copy.name} не связан с арматурой. Пропускаем.")
                    continue
                
                # Временно применяем модификатор, чтобы получить правильные координаты вершин
                try:
                    bpy.ops.object.modifier_apply(modifier=modifier.name)
                except RuntimeError as e:
                    print(f"Ошибка при применении модификатора Armature: {e}")
                    continue
        
        # Переходим в режим редактирования
        bpy.ops.object.mode_set(mode='EDIT')
        
        # Получаем BMesh представление mesh
        bm = bmesh.from_edit_mesh(mesh_copy.data)
        
        # Записываем список вершин
        file.write(f"===Vertices: {len(bm.verts)}\n")
        for vertex in bm.verts:
            file.write(f"Vertex {vertex.index}: {vertex.co}\n")
            
        # Убедимся, что у меша есть UV слой
        uv_layer = bm.loops.layers.uv.active
        if not uv_layer:
            file.write("UV слой не найден.\n")
        
        if uv_layer:
            file.write(f"===UV Coordinates:\n")
            file.write(f"Face count: {len(bm.faces)}\n")
            
            for face in bm.faces:
                file.write(f"Face {face.index}\n")
                file.write(f"UV Count: {len(face.loops)}\n")
                for loop in face.loops:
                    uv_coords = loop[uv_layer].uv
                    file.write(f"  UV {uv_coords}\n")
        
        # Записываем нормали
        file.write(f"===Normals:\n")
        for vertex in bm.verts:
            file.write(f"Vertex {vertex.index}: Normal {vertex.normal}\n")
        
        # Записываем треугольники (индексы вершин)
        file.write(f"===Triangles: {len(bm.faces)}\n")
        for face in bm.faces:
            if len(face.verts) == 3:  # Проверяем, что это треугольник
                verts_indices = [vert.index for vert in face.verts]
                file.write(f"Triangle: {verts_indices}\n")
        
        # Возвращаемся в объектный режим
        bpy.ops.object.mode_set(mode='OBJECT')
        
        # Записываем веса вершин
        file.write("=== Vertex Weights ===\n")
        for vertex in mesh_copy.data.vertices:
            file.write(f"Vertex {vertex.index}:\n")
            file.write(f"Vertex groups: {len(vertex.groups)}\n")
            for group in vertex.groups:
                group_name = mesh_copy.vertex_groups[group.group].name
                file.write(f"  Group: '{group_name}', Weight: {group.weight}\n")
        
        # Удаляем временную копию mesh
        bpy.data.objects.remove(mesh_copy)
    else:
        file.write(f"Объект с именем '{mesh_name}' не найден или не является mesh.\n")

    # Обработка арматуры и анимации
    if armature_obj and armature_obj.type == 'ARMATURE':
        
        # Получаем все ключевые кадры для арматуры
        file.write("=== Animation Keyframes ===\n")
        if armature_obj.animation_data and armature_obj.animation_data.action:
            action = armature_obj.animation_data.action
            
            # Собираем все уникальные ключевые кадры
            keyframes = set()
            
            # Логика для Blender 5.0 (Strip-based / ChannelBag structure)
            if hasattr(action, "layers"):
                for layer in action.layers:
                    if hasattr(layer, "strips"):
                        for strip in layer.strips:
                            # Проверяем наличие channelbags (согласно вашему dir(strip))
                            if hasattr(strip, "channelbags"):
                                for bag in strip.channelbags:
                                    for fcurve in bag.fcurves:
                                        for keyframe in fcurve.keyframe_points:
                                            keyframes.add(int(keyframe.co[0]))
                            
                            # На случай, если в этой версии используется единственное число
                            elif hasattr(strip, "channelbag") and strip.channelbag:
                                for fcurve in strip.channelbag.fcurves:
                                    for keyframe in fcurve.keyframe_points:
                                        keyframes.add(int(keyframe.co[0]))
            
            # Фоллбек для Legacy экшенов
            if not keyframes and hasattr(action, "fcurves"):
                for fcurve in action.fcurves:
                    for keyframe in fcurve.keyframe_points:
                        keyframes.add(int(keyframe.co[0]))

            keyframes = sorted(keyframes)

            # Сортируем ключевые кадры
            keyframes = sorted(keyframes)
            
            # Сохраняем координаты и матрицы поворота для каждой кости на каждом ключевом кадре
            file.write("=== Bone Transforms per Keyframe ===\n")
            file.write(f"Keyframes: {len(keyframes)}\n")
            for frame in keyframes:
                # Устанавливаем текущий кадр
                bpy.context.scene.frame_set(frame)
                bpy.context.view_layer.update()  # Обновляем сцену
                
                file.write(f"Frame: {frame}\n")
                for bone in armature_obj.pose.bones:
                    # Получаем координаты и матрицу поворота кости в мировом пространстве
                    matrix = bone.matrix
                    location = matrix.translation
                    rotation = matrix.to_euler()
                    
                    # Записываем данные
                    file.write(f"  Bone: {bone.name}\n")
                    file.write(f"    Location: {location}\n")
                    file.write(f"    Rotation: {rotation}\n")
                    file.write(f"    Matrix:\n")
                    for row in matrix:
                        file.write(f"      {row}\n")
    else:
        file.write(f"Объект с именем '{armature_name}' не найден или не является арматурой.\n")

print("Данные сохранены в файл 'mesh_armature_and_animation_data.txt'")