привет, почему когда я включаю режим квартениона у set_transform в коде, то его ротация пропадает, но если режима нет (удален), то ротация показывается верно, хоть и в xyz euler изначально (нужно вручную переключать в  квартенион)

import bpy
import xml.etree.ElementTree as ET
from bpy.types import Panel, Operator
from bpy.props import StringProperty
from bpy_extras.io_utils import ImportHelper
import mathutils

bl_info = {
    "name": "F1 Track Grid Editor",
    "author": "AlonsoBeast",
    "version": (1, 0, 0),
    "blender": (3, 3, 0),
    "category": "3D View",
}

class IMPORT_OT_f1_track_grid(bpy.types.Operator, ImportHelper):
    bl_idname = "import.f1_track_grid"
    bl_label = "Import Grids.pssg"
    bl_options = {'REGISTER', 'UNDO'}

    filename_ext = ".pssg"
    
    filter_glob: StringProperty(
        default="*.pssg",
        options={'HIDDEN'},
    )

    def execute(self, context):
        self.report({'INFO'}, f"Attempting to load file: {self.filepath}")
        print(f"Attempting to load file: {self.filepath}")

        try:
            tree = ET.parse(self.filepath)
            root = tree.getroot()
            self.report({'INFO'}, "File loaded successfully. Importing nodes...")
            print("File loaded successfully. Importing nodes...")
            self.import_nodes(root.find('.//ROOTNODE'), None)  # Начать с корневого элемента
            return {'FINISHED'}
        except ET.ParseError as e:
            self.report({'ERROR'}, f"XML parsing error: {e}")
            print(f"XML parsing error: {e}")
            return {'CANCELLED'}
        except FileNotFoundError:
            self.report({'ERROR'}, "File not found.")
            print("File not found.")
            return {'CANCELLED'}
        except Exception as e:
            self.report({'ERROR'}, f"Failed to import file: {e}")
            print(f"Failed to import file: {e}")
            return {'CANCELLED'}

    def import_nodes(self, node, parent_empty):
        if node is None:
            print("No node to import.")
            return

        nickname = node.get('nickname')
        print(f"Importing node: {nickname}")

        transform = node.find('TRANSFORM')
        bounding_box = node.find('BOUNDINGBOX')

        if transform is None or bounding_box is None:
            self.report({'WARNING'}, f"Node '{nickname}' is missing TRANSFORM or BOUNDINGBOX data.")
            print(f"Node '{nickname}' is missing TRANSFORM or BOUNDINGBOX data.")
            return

        transform_values = list(map(float, transform.text.strip().split()))
        bounding_box_values = list(map(float, bounding_box.text.strip().split()))

        # Создаем пустышку (Empty) для узла
        empty = bpy.data.objects.new(nickname, None)
        bpy.context.collection.objects.link(empty)

        # Устанавливаем трансформацию пустышки
        self.set_transform(empty, transform_values)
        print(f"Created Empty: {nickname} with transform: {transform_values}")

        # Устанавливаем иерархию
        if parent_empty:
            empty.parent = parent_empty

        # Позиции для ноды в Blender отобразим корректно
        obj_x = transform_values[12]  # берем из 4-го столбца
        obj_y = transform_values[14]  # берем из 2-го столбца
        obj_z = transform_values[13]  # берем из 3-го столбца
        empty.location = (obj_x, -obj_y, obj_z)  # применяем корректное местоположение (Y инвертируется)

        print(f"Node {nickname} location set to: X={obj_x}, Y={-obj_y}, Z={obj_z}")

        # Обработка дочерних узлов (RENDERNODE)
        for render_node in node.findall('RENDERNODE'):
            r_nickname = render_node.get('nickname')
            r_transform = list(map(float, render_node.find('TRANSFORM').text.strip().split()))
            r_bounding_box = list(map(float, render_node.find('BOUNDINGBOX').text.strip().split()))

            print(f"Creating Plane: {r_nickname}")

            bpy.ops.mesh.primitive_plane_add(size=1, enter_editmode=False, align='WORLD', location=(0, 0, 0))
            plane_obj = bpy.context.active_object
            plane_obj.name = r_nickname

            self.set_plane_size(plane_obj, r_bounding_box)
            self.set_render_transform(plane_obj, r_transform)

            print(f"Set Plane: {r_nickname} size: {r_bounding_box} and transform: {r_transform}")

            plane_obj.parent = empty
            print(f"Plane {r_nickname} parented to Empty {nickname}")

        # Рекурсивный вызов для вложенных узлов
        for sub_node in node.findall('NODE'):
            self.import_nodes(sub_node, empty)

    def set_transform(self, obj, transform):
        # Устанавливаем выходные параметры матрицы для пустышки
        mat = mathutils.Matrix((
            (transform[0], transform[1], transform[2], transform[3]),
            (transform[4], transform[5], transform[6], transform[7]),
            (transform[8], transform[9], transform[10], transform[11]),
            (transform[12], transform[13], transform[14], transform[15]),
        ))

        # Устанавливаем мировую матрицу
        obj.matrix_world = mat

        # Получение вращения как кватернион
        quat = mat.to_quaternion()
        
        # Установка кватернионов
        obj.rotation_quaternion = mathutils.Quaternion((quat[0], quat[1], -quat[3], -quat[1]))  # Зеркальное отражение по оси Y
        
        print(f"Applied transform to {obj.name}, Quaternion: {obj.rotation_quaternion}")  # Отладочный вывод

    def set_render_transform(self, obj, render_transform):
        # Создаем матрицу из значений трансформации
        mat = mathutils.Matrix((
            (render_transform[0], render_transform[1], render_transform[2], render_transform[3]),
            (render_transform[4], render_transform[5], render_transform[6], render_transform[7]),
            (render_transform[8], render_transform[9], render_transform[10], render_transform[11]),
            (render_transform[12], render_transform[13], render_transform[14], render_transform[15]),
        ))

        # Извлечение координат
        obj.location.x = mat[3][0]          # X из матрицы
        obj.location.y = -mat[3][2]         # Y из матрицы (инвертируем)
        obj.location.z = mat[3][1]          # Z из матрицы

        # Получение вращения как кватернион
        quat = mat.to_quaternion()
        
        # Устанавливаем кватернионы
        obj.rotation_quaternion = mathutils.Quaternion((quat[0], quat[1], -quat[2], quat[3]))  # Зеркальное отражение по оси Y

        # Масштаб
        scale = mat.decompose()[2]
        obj.scale = scale

        # Отладочный вывод
        print(f"Applied render transform to {obj.name}: location={obj.location}, rotation={obj.rotation_quaternion}, scale={scale}")

        # Итоговые значения кватерниона для отладки
        w, x, y, z = obj.rotation_quaternion
        print(f"Quaternion for {obj.name}: W={w}, X={x}, Y={y}, Z={z}")

    def set_plane_size(self, plane, bounding_box):
        width = bounding_box[3] - bounding_box[0]
        depth = bounding_box[5] - bounding_box[4]
        plane.scale[0] = width / 2
        plane.scale[1] = depth / 2
        print(f"Set size for Plane {plane.name}: {width}, {depth}")

class F1_PT_Track_Grid_Editor(Panel):
    bl_label = "F1 Track Builder Toolkit"
    bl_idname = "F1_PT_track_grid_editor"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = "F1 Track Builder Toolkit"

    def draw(self, context):
        layout = self.layout
        layout.operator(IMPORT_OT_f1_track_grid.bl_idname, text="Import Grids.pssg", icon='IMPORT')

def register():
    bpy.utils.register_class(IMPORT_OT_f1_track_grid)
    bpy.utils.register_class(F1_PT_Track_Grid_Editor)

def unregister():
    bpy.utils.unregister_class(IMPORT_OT_f1_track_grid)
    bpy.utils.unregister_class(F1_PT_Track_Grid_Editor)

if __name__ == "__main__":
    register()