3
$\begingroup$

I am very new to Python and the Blender API. I am doing some scripting tests and I am trying to append a collection (named Cube_Collection) from a blend file (Cube.blend) into a new, current, blend file Scene Collection using a Python script. So far I have seen two methods:

  1. Using the append operator
bpy.ops.wm.append()
  1. Using the BlendDataLibraries
with bpy.data.libraries.load(filepath, link=link) as (data_from, data_to):

However I haven't managed to make any of them work and getting too deep into the second method gets me very confused. So far the only one that worked, and I don't really know how, using the second method, is:

with bpy.data.libraries.load(filepath) as (data_from, data_to):
    for attr in dir(data_to):
        setattr(data_to, attr, getattr(data_from, attr))

However: I don't want to append everything from the source blend file. Moreover, I am not sure what the "attr" expression refers to and in the BlendDataLibraries examples it is not explicitly clarified what is what (at least it's not obvious to a newcomer like me).

Do you have any suggestion on the issue?

$\endgroup$

1 Answer 1

3
$\begingroup$

Blend files are structured in containers for the different data types that are inherent to a Blender file. Here's the contents of a random blend file on my disk.

enter image description here

Here's a link to the docs showcasing all the possible libraries in a blend file.

The for attr in dir(data_to): loop traverses the entire libraries collections and copies (appends) them to the current file. You can see what all these attributes are with

with bpy.data.libraries.load(filepath) as (data_from, data_to):
    print(dir(data_from))

['actions', 'armatures', 'brushes', 'cache_files', 'cameras', 'collections', 'curves', 'fonts', 'grease_pencils', 'hair_curves', 'images', 'lattices', 'lightprobes', 'lights', 'linestyles', 'masks', 'materials', 'meshes', 'metaballs', 'movieclips', 'node_groups', 'objects', 'paint_curves', 'palettes', 'particles', 'pointclouds', 'scenes', 'screens', 'simulations', 'sounds', 'speakers', 'texts', 'textures', 'volumes', 'workspaces', 'worlds']

In your case you only want the collections container. data_from.collections is a list with the collection names. eg in my Cube.blend file I have only one collection, so I have this result

with bpy.data.libraries.load(filepath) as (data_from, data_to):
    print(data_from.collections)

['Cube_Collection']

You specifically want the collection named Cube_Collection. So you only need to add (append) this name to the data_to.collections container.

with bpy.data.libraries.load(filepath) as (data_from, data_to):
    data_to.collections.append("Cube_Collection")

It may be weird, but remember, data_to.collections is a list of collection names, it isn't a list of collection objects. The collection will then be "automagically" added thanks to the special syntax of the code you used. with in python lets the object that is operated upon know when some code has been executed, that way it will parse data_to and see if new objects have been added to its container.

Do note that if there is no collection named "Cube_Collection" in the source file, the code will execute without throwing an error.

However once you run this code, you will notice that no collection has been added to your file. In fact it has, it has just not been linked to your current scene.

If you switch the outliner to "Blend file" you will see your collection under there.

enter image description here

If you drag and drop it into your scene, it will be instantiated. You can execute this step by code by adding these two lines at the end of your script :

collection = bpy.data.collections.get("Cube_Collection")
bpy.context.scene.collection.children.link(collection)
$\endgroup$
1
  • $\begingroup$ Oh wow, this is a very in-depth explanation, thank you! It clarifies my doubts. To my understanding, the various elements inside the blend file library (eg. collections, materials, objects etc) are considered as attributes of the library? Also, I think the main issues I had once I've read your answer is the fact that my appended elements weren't being linked to my current scene, since I noticed things were in fact changing in my current blend file every time I executed the code. I'll revise my code today and will come back if anything arises, thank you! $\endgroup$
    – Alex Vith
    Commented Nov 4, 2022 at 7:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .