4
$\begingroup$

To get the selected object in viewport, we use :

bpy.context.selected_objects

But in outliner, if i select some objects there, then what is the python function to get/collect the selected objects in outliner ?

$\endgroup$
5
  • $\begingroup$ It is bpy.context.selected_objects as well... Have a look at: docs.blender.org/api/current/… $\endgroup$
    – brockmann
    Commented Dec 1, 2020 at 15:53
  • 1
    $\begingroup$ ... not if hidden or disabled... I don't think there is something to identify them in these cases. $\endgroup$
    – lemon
    Commented Dec 1, 2020 at 16:09
  • $\begingroup$ @brockmann Thanks but as lemon said , i can't use it. It ignores the hidden/disabled objects. Most the object that i select is disabled. So no API for this ? $\endgroup$
    – andio
    Commented Dec 1, 2020 at 16:20
  • $\begingroup$ Nope, can not find anything... $\endgroup$
    – brockmann
    Commented Dec 1, 2020 at 18:22
  • $\begingroup$ Thanks , so it's confirmed that the API does not exist for that task. $\endgroup$
    – andio
    Commented Dec 2, 2020 at 2:29

3 Answers 3

6
$\begingroup$

As of this commit you can use Context.selected_ids (undocumented for now) to get references for all object types selected in the outliner. Notice that the context of selected_ids attribute is restricted to the Outliner so you'd have to implement an Operator.


I'd also suggest use the bl_rna.identifier attribute to test against the actual type of object in order to filter the selection. Run the script, move your mouse over to the ouliner, press F3 and type Simple Outliner Op... and hit Return:

import bpy

class SimpleOperator(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "outliner.simple_operator"
    bl_label = "Simple Outliner Operator"
    
    @classmethod
    def poll(cls, context):
        return context.area.type == 'OUTLINER'

    def execute(self, context):
        objects_in_selection = {}
        for item in context.selected_ids:
            if item.bl_rna.identifier == "Collection":
                objects_in_selection.setdefault("Collections",[]).append(item.name)
            elif item.bl_rna.identifier == "Object":
                if item.type == 'MESH':
                    objects_in_selection.setdefault("Meshes",[]).append(item.name)
                elif item.type == 'LIGHT':
                    objects_in_selection.setdefault("Lights",[]).append(item.name)
                elif item.type == 'CAMERA':
                    objects_in_selection.setdefault("Cameras",[]).append(item.name)
            elif item.bl_rna.identifier == "Material":
                objects_in_selection.setdefault("Materials",[]).append(item.name)
        
        # Print the dict to the console
        print (objects_in_selection)
        return {'FINISHED'}

def register():
    bpy.utils.register_class(SimpleOperator)
def unregister():
    bpy.utils.unregister_class(SimpleOperator)

if __name__ == "__main__":
    register()

Console Output: {'Collections': ['Collection', 'Collection.001'], 'Cameras': ['Camera', 'Camera.001'], 'Meshes': ['Cube', 'Cube.001'], 'Lights': ['Light', 'Light.001']}

$\endgroup$
1
  • 1
    $\begingroup$ Can be used in conjunction with the new batch remove eg bpy.data.batch_remove(context.selected_ids) $\endgroup$
    – batFINGER
    Commented Jun 18, 2021 at 8:56
3
$\begingroup$

@brockmann's answer works perfect. I just copied his functionality for an easier use for python beginners:

Here in addition is just an answer you can just execute by copy and paste without to execute the add-on in the outliner:

import bpy
from bpy import context

for window in context.window_manager.windows:
    screen = window.screen
    for area in screen.areas:
        if area.type == 'OUTLINER':
            with context.temp_override(window=window, area=area):
                objects_in_selection = {}
                for item in context.selected_ids:
                    if item.bl_rna.identifier == "Collection":
                        objects_in_selection.setdefault("Collections",[]).append(item.name)
                    elif item.bl_rna.identifier == "Object":
                        if item.type == 'MESH':
                            objects_in_selection.setdefault("Meshes",[]).append(item.name)
                        elif item.type == 'LIGHT':
                            objects_in_selection.setdefault("Lights",[]).append(item.name)
                        elif item.type == 'CAMERA':
                            objects_in_selection.setdefault("Cameras",[]).append(item.name)
                    elif item.bl_rna.identifier == "Material":
                        objects_in_selection.setdefault("Materials",[]).append(item.name)
                
                # Print the dict to the console
                a = objects_in_selection.get("Collections")
                if a:
                    print ("selected collections are", a)
            
$\endgroup$
0
$\begingroup$

The following code could be used to get the value of context.selected_ids without limiting an Operator's execute() to the Outliner area:

def get_outliner_area(context):
    for area in context.screen.areas:
        if area is None:
            continue
        if area.type != 'OUTLINER':
            continue
        return area

def get_outliner_window(area):
   for region in area.regions:
       if region.type != 'WINDOW':
           continue
       return region

# we will override context to be able to access selected_ids

# assuming that context is defined
outliner_area = get_outliner_area(context)
outliner_window = get_outliner_window(outliner_area)

# deprecated since 3.2 but easy to use
context_overridden = context.copy()
context_overridden['area'] = outliner_area
context_overridden['region'] = outliner_window

# @brockmann's solution can then be used to output a nice dictionary
print(context_overridden['selected_ids'])

Console output: [bpy.data.objects['Material'], bpy.data.objects['Camera'], bpy.data.objects['Material.001'], bpy.data.objects['Material.002'], bpy.data.objects['Material.003'], bpy.data.objects['Armature']]

$\endgroup$
1
  • $\begingroup$ In Blender 3.5 it throws an error: KeyError: 'selected_ids' if you just run this as a script $\endgroup$ Commented Apr 13, 2023 at 6:09

You must log in to answer this question.

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