Walking the Outliner Hierarchy

I’m developing my own export script, which works fine to export the currently selected active object to a file in my own custom format. That’s fine.

I need to expand on it now so that it can save multiple objects. So my idea was that if the current object is an empty then it could iterate through the empty’s children and save each object to the file (using the function that exports a single object that I’ve got which works, so that’s already covered).

The problem is that, with the API, getting the active object on an empty just gives me a NoneType.

I thought of doing it backwards and iterating through all the scene’s objects, if the active object is None, seeing if its parent was the selected empty, and then saving it to the file. But I can’t get this to work at all, and it feels like a very hack-ish solution to the problem anyway.

Is there not a way with the Python API to, you know, access the scene hierarchy as seen in the Outliner window?

That is, somehow check if the active selection is an empty and, if it is, then get a list of its child objects, so I can write each of them out to the file.

And, if it isn’t, because the active selection is just a singular object, then I can skip that and just write the object directly (as files with a single object in them are valid too, but I also need this “one or more objects” functionality too, using the empty to effectively mark out which objects form the set of objects that need to be written to the file).

So, in a sentence, how would I do “if selected object is an empty, then get a list of its children” (where by “children” I mean the objects that are directly under it in the outliner hierarchy - the objects to which the empty are its parents)?

References to empties are definitely not NoneType, I think you are confusing references to objects and references to object data.

The following code will get you the behaviour you described:


import bpy

children = []

ob = bpy.context.active_object

if ob.type == 'EMPTY':
    children = ob.children

Note that if you were to look at ob.data, on an empty object that will return None, however parenting happens at object level, so you have no need to look at the data part.

Also note that you can easily make the above code recursive, if you also want grandchildren, etc.

Yeah, I think I was looking in the wrong place - trying to find it in the ob.data, rather than at the object level - but I rearranged things to do it a different way in the meantime, just to make it work. I’ll rearrange things again and try it out.

Thanks.

I see the mistake I was making. When calling my function to save an object, I was passing the ob.data to it, not the object itself. So I was operating at the wrong level, so to speak, and was confusing myself.

It’s all working as intended now. Saves individual meshes, saves the children of an empty is it’s an empty, and tidily reports an error otherwise.

Good stuff. Thanks again.