2
$\begingroup$

I have a simple operator which creates an empty object and immediately prints out the object's name:

import bpy

class createEmpty(bpy.types.Operator):
    """Create an empty object"""
    bl_idname = 'make.empty'
    bl_label = 'Create an empty object'

    def execute(self, context):
        bpy.ops.object.empty_add(type='PLAIN_AXES')
        print(bpy.context.object.name)
        return {'FINISHED'}

class createEmptyPanel(bpy.types.Panel):
    bl_idname = 'create_empty_panel'
    bl_label = 'create empty object'
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = 'object'

    def draw(self, context):
        layout = self.layout
        row = layout.row()
        row.operator('make.empty')

bpy.utils.register_class(createEmpty)
bpy.utils.register_class(createEmptyPanel)

When I run this from the console, it creates an empty object and prints its name, 'Empty'. However, when I click the button in the UI, it creates an empty object, but prints the name of the object that was selected, in my case 'Cube'.

Why is this? Is there a better way to select the object I just created, other than bpy.context.object?

$\endgroup$
3
$\begingroup$

The simplest solution is to use active_object instead:

def execute(self, context):
    bpy.ops.object.empty_add(type='PLAIN_AXES')
    print(bpy.context.active_object.name)
    return {'FINISHED'}

Blender doesn't switch the bpy.context.object until after the createEmpty operator has completed, hence the Cube's name was being printed. Your operator is invoked from the createEmptyPanel which has bl_context = 'object', I suspect this has built in blocking of bpy.context.object changes.

Avoid this behaviour by using the lower level bpy.data.objects.new to make the empty. Change the execute function to avoid using bpy.ops.object.empty_add(), like:

import bpy

class createEmpty(bpy.types.Operator):
    """Create an empty object"""
    bl_idname = 'make.empty'
    bl_label = 'Create an empty object'

    def execute(self, context):
        # bpy.ops.object.empty_add(type='PLAIN_AXES')
        scene = context.scene
        objects = bpy.data.objects
        mt = objects.new("empty_name", None)
        mt.location = (0, 2, 1)
        mt.empty_draw_size = 2
        mt.empty_draw_type = 'PLAIN_AXES'
        scene.objects.link(mt)
        scene.update()
        print(mt.name)
        return {'FINISHED'}

class createEmptyPanel(bpy.types.Panel):
    bl_idname = 'create_empty_panel'
    bl_label = 'create empty object'
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = 'object'

    def draw(self, context):
        layout = self.layout
        row = layout.row()
        row.operator('make.empty')

bpy.utils.register_class(createEmpty)
bpy.utils.register_class(createEmptyPanel)

It's a bit more verbose, but it does immediately give you a reference to the new empty.

| improve this answer | |
$\endgroup$

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.