3
$\begingroup$

I am creating a bone, and then a collection with a specific name if it does not exist, with the following function:

def make_collection(collection_name):
    if collection_name in bpy.data.collections:
        return bpy.data.collections[collection_name]
    else:
        new_collection = bpy.data.collections.new(collection_name)
        bpy.context.scene.collection.children.link(new_collection)
        return new_collection

The collection is linked to the master collection so it's on the top of the hierarchy, and now i try link it to the collection.

I create the collection:

root = make_collection("bat")

and later on in the code, i create a bone (although is an empty since it's a standalone bone), and i try to link it like this:

bpy.ops.object.empty_add(type='CUBE')
bone = bpy.context.active_object
bone.name = data[i].name
#bpy.ops.collection.objects_add_active(collection=root)
root.objects.link(bone)

Even though it's called root, root is not the master collection, just to clarify. The result is the following:

Same object on both collections.

It's the same empty i created, that appears twice in both collections. Although an idea would be to just delete other collections, 2 will appear still, one in the master collection, and one in the collection i created.

Also it's the same item since, if i click one, both get selected at the same time, so there's only one empty in the scene, i just can choose where to click it from.

Now the problem is i'm doing this with several objects in a loop, so i would be basically duplicating the object list twice, and that's pretty redundant.

If i don't use the root.objects.link code at all, the objects would just be on the master collection, but i want them to be on the collection i specifically created.

Is there any way to fix this? I'm not sure why it appears on both collections and i'm very confused. I'm fairly new with the blender API, so i'm not sure what i'm doing wrong.

Thanks for reading!

$\endgroup$
4
  • $\begingroup$ There's probably a better answer, but in the meantime use unlink(bone): >>> bpy.data.collections['bat'].objects.link(bpy.data.objects['Empty']) >>> bpy.data.collections['bat'].objects.unlink(bpy.data.objects['Empty']) $\endgroup$ – Ron Jensen Aug 28 '20 at 1:35
  • $\begingroup$ I tried this but, wouldn't this go back to step 1? I create the empty and by default it appears in the master collection, i link it with the code, but then i undo the link by unlinking it. While it only shows it once which is good, it is not inside the bat collection which was the purpose of the code. I'm sorry if i did not explain myself properly $\endgroup$ – Seyren Windsor Aug 28 '20 at 1:50
  • $\begingroup$ My bad, the second line should have read: bpy.data.collections['Collection'].objects.unlink(bpy.data.objects['Empty']) $\endgroup$ – Ron Jensen Aug 28 '20 at 1:55
  • $\begingroup$ Oooh okay, that makes more sense! Yeah i guess i'll do this workaround in the meantime! thanks! $\endgroup$ – Seyren Windsor Aug 28 '20 at 2:03
3
$\begingroup$

So I'm going to give two answers: the first for the question you actually asked regarding doubling linking objects, and the second for the question you wanted to ask, that being how do you create objects in a specific collection in the first place.

Given an object called 'bone' which was created in the current collection and a collection called 'root' you want to move 'bone' from the active collection to the 'root' collection:

# use unlink(bone)
root.objects.link(bone)
bpy.context.collection.objects.unlink(bone) # this is the active collection

The better way would be to create 'bone' in the 'root' collection in the first place. In the script below I do that by changing the active collection.

import bpy


def set_collection(collection_name):
    if collection_name in bpy.context.view_layer.layer_collection.children:
        root=bpy.context.view_layer.layer_collection.children[collection_name]
    else:
        coll=bpy.data.collections.new(collection_name)
        bpy.context.scene.collection.children.link(coll)
        root=bpy.context.view_layer.layer_collection.children[coll.name]

    bpy.context.view_layer.active_layer_collection=root
    return(root)

root = set_collection('Soear')
bpy.ops.object.empty_add(type='CUBE')

bone = bpy.context.active_object
$\endgroup$
1
  • $\begingroup$ This answer is amazing! Thank you so much for telling me how to also apply it better, it's way more clean by doing it the second way, but i could not figure out the API properly. Greatly appreciated! $\endgroup$ – Seyren Windsor Aug 28 '20 at 3:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.