Create groups in Blender 2.8, 2.9

Hello,

Pistiwique made kindly an add-on for me a year ago and I can’t reach him now.

He made 2 versions. A 2.79 version that use CTRL + G to make groups from a selection of objects and name groups with the name of objects and a 2.8 version that does the same thing but make a collection and don’t use CTRL + G (at this time I was not sure Blender would keep using groups).

I just need a little modification so the 2.8 version use CTRL + G to make a collection that doesn’t appear in the Outliner.

I let you the 2 versions. I think it’s pretty easy for someone who knows Python.

asturias_tools_2_8.zip (3.6 KB) asturias_tools_2_79.zip (3.5 KB)

The part that needs to be changed :

class ASTURIASTOOLS_OT_create_collections(Operator):
    ''' Create and name groups from selected objects '''
    bl_idname = "asturiastools.create_collections"
    bl_label = "Create groups"
    bl_options = {'REGISTER'}

    @classmethod
    def poll(cls, context):
        return context.selected_objects

    def execute(self, context):
        D = bpy.data
        active = context.active_object
        selection = context.selected_objects
        bpy.ops.object.select_all(action="DESELECT")

        for obj in selection:
            if D.collections.find(obj.name) != -1:
                continue

            context.view_layer.objects.active = obj
            obj.select_set(True)
            bpy.ops.object.move_to_collection(collection_index=0,
                                              is_new=True,
                                              new_collection_name=obj.name)
            obj.select_set(False)

        for obj in selection:
            obj.select_set(True)

        context.view_layer.objects.active = active

        return {'FINISHED'}

Thanks for help.

Is anything unclear ?

class ASTURIASTOOLS_OT_create_collections(Operator):
    ''' Create and name groups from selected objects '''
    bl_idname = "asturiastools.create_collections"
    bl_label = "Create groups"
    bl_options = {'REGISTER', 'UNDO'}

    move_objects: BoolProperty(
            name="Move objects",
            default=True,
            description="Move selected objects to new collections otherwise just link them"
            )
    
    create_root: BoolProperty(
            name="Create Root Collection",
            default=False,
            description="Create a collection and parent all other collections to it."
            )

    collection_per_object = BoolProperty(
            name="Create A Collection Per Object",
            default=True,
            description="Create a collection per object or just create one collection"
    )

    link_collections = BoolProperty(
            name="Link Collections To Scene",
            default=True,
            description="Link the new collections to the current scene or just create them and set their fake user flags"
    )

    @classmethod
    def poll(cls, context):
        return context.selected_objects

    def execute(self, context):
        active = context.active_object
        selection = context.selected_objects
        scene = context.scene

        c_list = []

        if self.collection_per_object:
            for obj in selection:
                c = bpy.data.collections.new(obj.name)
                
                if self.move_objects:
                    for collection in obj.users_collection:
                        collection.objects.unlink(obj)  

                c.objects.link(obj)
                c.use_fake_user = not(self.link_collections)
                c_list.append(c)
        else:
            c = bpy.data.collections.new("")
            for obj in selection:
                if self.move_objects:
                    for collection in obj.users_collection:
                        collection.objects.unlink(obj)  

                c.objects.link(obj)
                c.use_fake_user = not(self.link_collections)
            c_list.append(c)


        if self.create_root:
            root = bpy.data.collections.new("")
            root.use_fake_user = not(self.link_collections)
            for c in c_list:
                root.children.link(c)
            if self.link_collections:
                scene.collection.children.link(root)

        elif self.link_collections:
            for c in c_list:
                scene.collection.children.link(c)     

        return {'FINISHED'}

If you want it to work similar to how the collection.create operator does then you need to disable both the “move objects” and “link collections to scene” options, which you can either do directly in the script or when you assign the operator “asturiastools.create_collections” to a hotkey in your Blender preferences, or just whenever you first run the operator.

Hello and thanks for your answer. I got this error trying your script :

Traceback (most recent call last):
  ***\tools.py", line 75, in execute
    description="Link the new collections to the current scene or just create them and set their fake user flags"
  ***\modules\bpy_types.py", line 721, in __getattribute__
    return super().__getattribute__(attr)
AttributeError: 'ASTURIASTOOLS_OT_create_collections' object has no attribute 'move_objects'

location: <unknown location>:-1

I just would like to have collection like the one surrounding by green in the screenshot :

I’m not sure that all functions you put are necessary ?

OK, now that I believe I know what you want here is a simpler version which hopeful will work for you:

class ASTURIASTOOLS_OT_create_collections(Operator):
    ''' Create and name groups from selected objects '''
    bl_idname = "asturiastools.create_collections"
    bl_label = "Create groups"
    bl_options = {'REGISTER'}

    @classmethod
    def poll(cls, context):
        return True

    def execute(self, context):
        selection = context.selected_objects

        for obj in selection:
            
            # You can remove this block of code if you want but it's checking if the 
            # object already is linked to a collection with the same name as it, and 
            # if it is it just skips to the next obj.
            skip = False
            for c in obj.users_collection:
                if c.name == obj.name:
                    skip = True
                    break
            if skip:
                continue
            
            # You can remove this block of code if you want but it's checking if there is 
            # already a collection with the same name as this object, and if there is it 
            # adds the object to that collection rather then creating a new collection that 
            # Blender will be forced to rename.
            skip = False 
            for c in bpy.data.collections:
                if c.name == obj.name:
                    c.objects.link(obj)
                    skip = True
                    break
            if skip:
                continue

            # Keep this code!!!
            c = bpy.data.collections.new(obj.name)
            c.use_fake_user = True
            c.objects.link(obj)

        return {'FINISHED'}

Hello,

thanks you very much, it works perfecly. I removed the 2 first blocks of code as I use the add-on on files that don’t have collections at start excepted the default collection “Collection” :stuck_out_tongue:.

Explanation of how I use this part of the add-on : I create a file and put assets I found on the web, let’s say for example people. So I import them in the file, rework the shaders or geometry if needed and than, as I want to link them in future projects, I use the add-on as objects have to be in collections to be linked but with your code change, it’s easy on the eye in the outliner :slight_smile:.

1 Like