Help adding new scene, collection, objects in 2.8

OK, so I was trying to get a addon to work in blender 2.8 ,but with the changes I am having issues.
Can somebody help me figure out how to add a new scene, collection, rename collection to match scene name, and then add object to that collection? Adding the scene is simple ,but I can’t figure the rest out.

You can create a data block for new collection with:

p = bpy.data.collections.new('Poo')

but I have no idea how to link that with a scene using Python.

If you use the outliner to create a new collection and want to link an object to it:

txt = bpy.context.scene.objects['Text']    # assign text object to variable
bpy.context.scene.collection.children.keys()     # list of collections
col2 = bpy.context.scene.collection.children['Collection 2']    # get this collection
col2.objects.link(txt)    #link text object

I can’t find anything for actually moving it into the collection though, so it’s still
hanging out there in the middle of the Master Collection.
I’m not sure 2.8 has complete Python functionality yet. At least not for Collections.

1 Like

Have a look at 2.80/scripts/modules/bpy_extras/object_utils.py

Hello! А lot of time has passed, but can anyone come in handy yet.

How to link new collection to scene (master collection)

# get an active object
obj = bpy.context.object

# create new collection
newCol = bpy.data.collections.new('Yammy')
#.... or find the existing collection
newCol = bpy.data.collections['Yammy']

# link the newCol to the scene
bpy.context.scene.collection.children.link(newCol)

# link the object to collection
newCol.objects.link(obj)
# ... or link through bpy.data
bpy.data.collections['Yammy'].objects.link(obj)

Hope it’s useful =)

6 Likes

Thank you very much, this info helped me a lot. May I still ask you something else? I’m trying to link collections via scripting, and even if I’m able to do it through the console inside blender when I try to run my script it gives me a keyError: as if the first collection I create doesn’t exist, which actually does exist.

here is the code, the error pops on the second line of the IF statement, as if my variable “O” doesn’t exist, and it does because I see it in the outliner after running the script.

import bpy


O = bpy.data.collections.new("pepe")
        
bpy.context.scene.collection.children.link(O)

        
tier = "coco"           
            
if bpy.data.collections.get(tier) is None:
    """ global tier_O """
    tier_O =  bpy.data.collections.new("coco")
    bpy.data.collections[str(O)].children.link(bpy.data.collections[str(tier_O)])
                
            
else:
    tier_O = bpy.data.collections[tier]
    bpy.data.collections[str(O)].children.link(bpy.data.collections[str(tier_O)])```

Ok solve it myself!

I was converting my variable (collection) “O” into a string when I only had to get its name like this “O.name”

Also you don’t have to use a string key :wink:

Try this:

import bpy

O = bpy.data.collections.new("pepe")
       
bpy.context.scene.collection.children.link(O)
        
tier = "coco"           
            
if bpy.data.collections.get(tier) is None:
    """ global tier_O """
    tier_O =  bpy.data.collections.new("coco")
    O.children.link(tier_O)
            
else:
    tier_O = bpy.data.collections[tier]
    O.children.link(tier_O)

Because you can work with objects which was prepared

2 Likes

mmm , not sure, with this i test, and link object is already in principal collection. I think this because, if when you create a new collection , the new collection is “Active” and then object is put in in automatic, but (i try this) if you want link object and the collection selected is another this is the problem of double link object in 2 collection. I try to find , how to “get” the active collection , because i think is a possibility to unlink object from active collection example: my_act_coll = active.scene.collection (not found the api" and from this: my_act_coll.object.unlink(obj) for unlink object and link to any collection

ob= bpy.context.scene.collection.children[‘ob’] #get collection ‘ob’
for obj in ob.objects:
obj.select_set(True)
to make objects selected of a collection[‘name’]

I was trying to add an object(s), into a collection, which is not selected/active, necessarily. Another one could be selected in the UI, but I want to add to a specific one.

If I try to use this, it says its not found in the master collection.
https://docs.blender.org/api/2.80/bpy.ops.collection.html?highlight=collection#module-bpy.ops.collection
bpy.ops.collection. objects_add_active ( collection=‘’ )

If I do what someone said above, it links it to the collection, but then there are 2 copies, or almost looks like that in the UI. It didn’t actually move it…

bpy.data.collections[‘collection_name’].objects.link(obj)

Any ideas? Thank you!

Edit:

I solved it. I couldn’t find an example, but I thought maybe I had to unlink from the main scene, which 'seems" to work/have fixed it…

collection = bpy.data.collections.get(‘collection_name’)
collection.objects.link(obj)
scn.collection.objects.unlink(obj)

Edit:

Although now I realized, if I have the layer I want to add to, selected, it tries to Add it twice, and gives error… so there must be a way to get the active layer name or index or something?

Edit:

Whew… so I think… I finally solved it.

Basically before I click a button/run the Def/Function, I have to set the Active Collection to the Scene. Then I can Add it where I want, without it saying it’s in the same place twice or not giving an errorr, but still having it in 2 spots at once.

Set Active Collection to Scene.

def execute(self, context): 
    
        bpy.context.view_layer.active_layer_collection = bpy.context.view_layer.layer_collection

        runDef()

runDef(

        if scn.collection_selection != '':
        collection = bpy.data.collections.get(scn.collection_selection)
                        
         activeCollection = (bpy.context.view_layer.active_layer_collection).name
 
         if (scn.collection_selection) != activeCollection:
              collection.objects.link(obj)
                          
           if obj.name in scn.collection.objects:
               scn.collection.objects.unlink(obj)
)