Highlight/Activate Object in Outliner using Python

Hi guys,

I am writing a script that loops through a list of objects in the scene and while it’s looping it imports .mdd caches to each of the objects of list.
I notice that my script doesn’t work because I am unable to activate/highlight the object in the outliner while I am looping.
I am using bpy.ops.object.select_all(action=‘DESELECT’) and bpy.ops.object.select_pattern(pattern=obj) to deselect all objects and select the object I want to import the caches to, but if they are not highlighted in the outliner, my script doesn’t import the cache to the right object.

Sounds a bit odd that I need to highlight the object in the outliner. The way I figured this out was importing the cache to only one object in the scene with the object highlighted. Also when the script loops, only one object stays highlighted in the outline and that’s why I believe the script isn’t importing the cache to the right object.

This is my script:

def import_caches_to_objs(objs_name, selected_path):
‘’’
Loops through list of objects provided and import mdd caches to them.
‘’’
for obj in objs_name:
print(‘Importing Cache’)
filepath=selected_path + ‘/’ + obj + ‘.mdd’ # Making the filepath for the .mdd cache
print(filepath)
bpy.ops.object.select_all(action=‘DESELECT’) # Deselecting object
bpy.ops.object.select_pattern(pattern=obj) # Selecting object from list
bpy.ops.import_shape.mdd(filepath=filepath, frame_start=1) # Importing cache to selected object
print(‘Cache Imported’)
return objs_name

The scripts imports every cache, but it doesn’t import the caches to the right objects in the loop. It imports the cache to the highlighted object.
Am I doing the right way? Or is there a proper way to select the object using python overriding the highlighted object in the outliner?

Thank you for your attention in advance

Rodrigo Guimaraes

pS: Sorry for the code without indent, I don’t know how to quote the code lines.

Use code tags [noparse]

paste code here

[/noparse] to highlight code.

The object “highlighted” in the outliner is the active object, as opposed to selected objects.

To make an object active you can use


scene = context.scene
scene.objects.active = obj

A little test in console


>>> C.scene.objects.active = None
>>> C.scene.objects.active
>>> C.object

And you can have a selected object and no active object. Most operators work (primarily) on the active object.

Change the body of your method to something like


def import_caches_to_objs(scene, obj_names, selected_path):
    bpy.ops.object.select_all(action='DESELECT') # Deselecting all
    for name in obj_names:
        print('Importing Cache')
        # get out of the habit of string concat.
        filepath = "%s/%s.mdd" % (selected_path, name)
        # filepath=selected_path + '/' + name + '.mdd' # Making the filepath for the .mdd cache
        print(filepath)


        obj = scene.objects.get(name)  # the object or None
        scene.objects.active = obj
        bpy.ops.import_shape.mdd(filepath=filepath, frame_start=1) # Importing cache to selected object
        print("Cache Imported for %s" % name)
    return obj_names # ???

Hey batFinger,

Thank you very much for your help. You’re always around to help me out here. :wink:
My script is working fine now.

Just one question about your code lines.

When I tested the line below in the console, it worked but not in my script:


C.scene.objects.active = None

So I had to type in my script:


bpy.context.scene.objects.active = None

Also for:


scene = context.scene

I had to type:


bpy.context.scene

Was that a typo error? Or Am I missing something?
I am asking these questions because I am new to Blender’s python scripting and I really would like to understand it better.

Cheers

Rodrigo Guimaraes

Sorry for the confusion.

I was pointing out that the active object could be unset, ie set to None while you still had selected objects, in which case a lot of operators will not work.

C is the convenience variable for bpy.context, D for bpy.data in the console. As pointed out when the console is first opened.

Yep in most (if not all) cases the context is bpy.context. My suggestion tho is to avoid using the full bpy.context… in code as most class methods pass the context as a parameter, for example, operator poll, invoke, execute and cancel as well as panel poll and draw methods.


class MyOp(Operator):
    @classmethod
    def poll(cls, context):
    obj = bpy.context.scene.objects.active  # IMO this is bad as opposed to

    scene = context.scene
    obj = scene.objects.active
    return (obj is not None)

Putting in the simple line


context = bpy.context

in test code, makes copy and paste later when you are making operators / panels etc a lot easier, which sooner or later needs to be done to make the code “operational” to use in the blender interface rather than via text or console.