Blendfile: Get String IDProperty

This is an old article from 2016. I was a kid. I learned a lot since then, so please do think twice when taking advice from me as a kid.

So, this took me while to figure out, so I want to share it. blendfile.py is a one-file module in blender/2.7x/addons/io_blend_utils/blend/ for reading and writing blend files. This can be especially useful if you require only one or two properties of the file: Now you can do so without loading the entire file in blender, which takes a while.

For the Wonderland Engine, I required the names and resolutions of the texture altases (uv_texture_atlas addon) from a bunch of blend files, here is how I did that:

blends = [...]
atlases = []
for blend_file_path in blends:
    with blendfile.open_blend(blend_file_path) as blend:
        scenes = [block for block in blend.blocks if block.code == b'SC']

        for scene in scenes:
            # get custom properties
            properties = scene.get_pointer((b'id', b'properties'))

            # iterate through all the property groups
            iter = properties.get_pointer((b'data', b'group', b'first'))
            while iter is not None:
                group = iter.get_pointer((b'data', b'pointer'))
                if group is not None:

                    # iterate over all the properties
                    prop = group.get_pointer((b'data', b'group', b'first'))
                    while prop is not None:
                        name = prop.get(b'name')

                        for x in prop.items_recursive_iter():
                            print(repr(x))

                        if name == 'name':
                            offset = prop.get((b'data', b'pointer'))
                            blk = blend.block_from_offset.get(offset)
                            blend.handle.seek(blk.file_offset, os.SEEK_SET)
                            atlas_name =
                                blendfile.DNA_IO.read_string0(blend.handle,
                                                              prop.get(b'len'))
                        elif name == 'resolutionX':
                            resX = prop.get((b'data', b'val'))
                        elif name == 'resolutionY':
                            resY = prop.get((b'data', b'val'))

                        prop = prop.get_pointer(b'next')

                    atlases.append((atlas_name, 2**(resX+8), 2**(resY+8)))

                iter = iter.get_pointer(b'next')

for atlas in atlases:
    print(repr(atlas))

Since the blendfile module is not documented at all (only used for specific internal use cases), I hope this helps someone who has a similar use case.

Good luck!

This post was imported from my old wordpress site.