Blendfile: Get String IDProperty

This is an old ar­ti­cle from 2016. I was a kid. I learned a lot since then, so please do think twice when tak­ing ad­vice from me as a kid.

So, this took me while to fig­ure out, so I want to share it. blend­file.py is a one-file mod­ule in blender/2.7x/ad­dons/io_blend_u­tils/blend/ for read­ing and writ­ing blend files. This can be es­pe­cial­ly use­ful if you re­quire on­ly one or two prop­er­ties of the file: Now you can do so with­out load­ing the en­tire file in blender, which takes a while.

For the Won­der­land En­gine, I re­quired the names and res­o­lu­tions of the tex­ture al­tases (uv_­tex­ture_at­las ad­don) 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 blend­file mod­ule is not doc­u­ment­ed at all (on­ly used for spe­cif­ic in­ter­nal use cas­es), I hope this helps some­one who has a sim­i­lar use case.

Good luck!

This post was im­port­ed from my old word­press site.