Change data print formatting

I have a script that prints out objects data for each frame. Currently it prints out the data for each frame in one line for all the objects. How can I change it to split the lines to print the data for each object and still have the frame number in the beginning of the line?

This is the original code:

import bpy


running_check = {}


def pack_frame_info(idx):
   
    f = bpy.context.scene.frame_current
    dp_str = []
    dp_str.append(str(f))
    for obj in bpy.data.objects:
        
        if not (tuple(True if i==idx else False for i in range(20)) == obj.layers[:]):
            continue
           
        mat = obj.matrix_world
        loc = mat.to_translation()
        rot = mat.to_3x3().to_quaternion()
        scale = obj.dimensions
        
        apt = {
            'obj': obj.name,
            'qtX': round(rot.x,3),
            'qtY': round(rot.y,3),
            'qtZ': round(rot.z,3),
            'qtW': round(rot.w,3),
            'loX': round(loc.x,3),
            'loY': round(loc.y,3),
            'loZ': round(loc.z,3),
            'scX': round(scale.x,3),
            'scY': round(scale.y,3),
            'scZ': round(scale.z,3)
        }


        j = '|{obj}|<{loX},{loY},{loZ}>|<{qtX},{qtY},{qtZ},{qtW}>|<{scX},{scY},{scZ}>'.format(**apt)


        stored_values = running_check.get(obj.name)
        if not stored_values:
            running_check[obj.name] = j
        else:
            if (stored_values == j):
                # means it was the same, and can be skipped.
                continue
            else:
                # means we proceed to adding this to the output, and store it for next
                # iteration.
                running_check[obj.name] = j
 

        dp_str.append(j)
    return ' '.join(dp_str)


def RunPerFrame(scene):
    scene.update()
    k = pack_frame_info(0)
    print(k)    




bpy.app.handlers.frame_change_pre.append(RunPerFrame)

Can you give an example of the output you have, and the output you want?

Currently I have this: all objects are printed in one line for each frame:

frame1|object1|loc|rot|scale|object2|loc|rot|scale|object3|loc|rot|scale|…
frame2|object1|loc|rot|scale|object2|loc|rot|scale|object3|loc|rot|scale|…

what I need is to print data for each object separately with a frame number in the beginning of the line:

frame1|object1|loc|rot|scale
frame1|object2|loc|rot|scale
frame1|object3|loc|rot|scale
frame2|object1|loc|rot|scale
frame2|object2|loc|rot|scale
frame2|object3|loc|rot|scale

Also I need some way to enable or disable the bottom part of the script that ignores unchanged data.

Try this:


import bpy




running_check = {}




def pack_frame_info(idx):
   
    f = bpy.context.scene.frame_current
    dp_str = []
    #dp_str.append(str(f))
    for obj in bpy.data.objects:
        
        if not (tuple(True if i==idx else False for i in range(20)) == obj.layers[:]):
            continue
           
        mat = obj.matrix_world
        loc = mat.to_translation()
        rot = mat.to_3x3().to_quaternion()
        scale = obj.dimensions
        
        apt = {
            'frm': f,
            'obj': obj.name,
            'qtX': round(rot.x,3),
            'qtY': round(rot.y,3),
            'qtZ': round(rot.z,3),
            'qtW': round(rot.w,3),
            'loX': round(loc.x,3),
            'loY': round(loc.y,3),
            'loZ': round(loc.z,3),
            'scX': round(scale.x,3),
            'scY': round(scale.y,3),
            'scZ': round(scale.z,3)
        }




        j = '|{frm}|{obj}|<{loX},{loY},{loZ}>|<{qtX},{qtY},{qtZ},{qtW}>|<{scX},{scY},{scZ}>
'.format(**apt)




        stored_values = running_check.get(obj.name)
        if not stored_values:
            running_check[obj.name] = j
        else:
            if (stored_values == j):
                # means it was the same, and can be skipped.
                continue
            else:
                # means we proceed to adding this to the output, and store it for next
                # iteration.
                running_check[obj.name] = j
 


        dp_str.append(j)
    return ' '.join(dp_str)




def RunPerFrame(scene):
    scene.update()
    k = pack_frame_info(0)
    print(k)    






bpy.app.handlers.frame_change_pre.append(RunPerFrame)


Yes, that works perfect, I didn’t think it would be so simple, thanks a lot!