[SOLVED] Rename object after import

Hello
I want write very simple button. Who is opening window with filepatch, useris choosing a object,and after import, Blender is rename object. I wrote such a script:

class Import(bpy.types.Operator):
    """Import"""
    bl_idname = "fp.import"
    bl_label = "Import"
    
    def execute(self,context):
        for obj in bpy.data.objects:
            obj.tag = True        
        if not bpy.data.filepath:
            bpy.ops.import_mesh.stl('INVOKE_AREA')
        else:
            bpy.ops.import_mesh.stl('INVOKE_AREA')    

        self.report({'INFO'}, 'File saved.')
             
        for obj in bpy.context.selected_objects:
            obj.name = "Bacon"
            obj.data.name = "Bacon"                       

        return {'FINISHED'}

But is not working. Name is changing, when I press second time a button with this class.
Can any one can help me ?

Greets

Hello,

The reason it does not work is an Asynchronous issue in your code.

You call the operator invoke function :
bpy.ops.import_mesh.stl('INVOKE_AREA')
Basically, it means this line instantly returns {RUNNING_MODAL}
In that case, the import_mesh operator is running asynchronously.
So, this loop :

for obj in bpy.context.selected_objects:
            obj.name = "Bacon"
            obj.data.name = "Bacon"    

Is already executed when you are browsing your files.
To make sure you can try to add these prints :

print("before")
bpy.ops.import_mesh.stl('INVOKE_AREA')
print("after")

Console shows :

before
after
Import finished in 0.0002 sec.

Which shows that your import is actually run after the “after” print


What you want is having the import_mesh blocking (i.e. synchronously) so that, when it’s finished, you can run some piece of code AFTER it’s finished.
The way to run import_mesh synchronously is to call explicit files parameters like so :
bpy.ops.import_mesh.stl(filepath=some_path_to_file)


Finaly, to do so you will need the user to be able to choose a file. That is done by calling context.window_manager.fileselect_add in your Operator Invoke function.


To conclude :

import bpy

class Import_STL_Custom(bpy.types.Operator):
    bl_idname = "object.import_stl_custom"
    bl_label = "Import STL Custom"

    # Choosen path will be stored here
    filepath : bpy.props.StringProperty(subtype="FILE_PATH")
    # Filter files to show only STL
    filter_glob : bpy.props.StringProperty(
        default="*.stl;",
        options={'HIDDEN'},
    )

    def invoke(self, context, event):
        # Call the "choose file" browser
        context.window_manager.fileselect_add(self)
        return {"RUNNING_MODAL"}

    def execute(self, context):
        # Explicit import_mesh call with self.filepath saved with invoked fileselect_add
        bpy.ops.import_mesh.stl(filepath=self.filepath)
        # Piece of code to be run AFTER import
        for obj in bpy.context.selected_objects:
            obj.name = "Bacon"
            obj.data.name = "Bacon"
        return {"FINISHED"}

def register():
    bpy.utils.register_class(Import_STL_Custom)

def unregister():
    bpy.utils.unregister_class(Import_STL_Custom)

if __name__ == "__main__":
    register()
    bpy.ops.object.import_stl_custom("INVOKE_DEFAULT")

See you :slight_smile: ++
Tricotou

2 Likes

Wooow.
Thaqnk You for this example. I have problems with invoke
But I have one problem. When I run a script without any problems, window manager is opening. But when I put this code to button, window manager is not opening and script is taking object from filepath,
which I wrote.
Greets, and one more time thank You for help.

You might add the button in a bad way.
Doing like so (code from panel template) works very fine
(Button is in Scene Properties Panel)

import bpy


class Import_STL_Custom(bpy.types.Operator):
    bl_idname = "object.import_stl_custom"
    bl_label = "Import STL Custom"

    # Choosen path will be stored here
    filepath : bpy.props.StringProperty(subtype="FILE_PATH")
    # Filter files to show only STL
    filter_glob : bpy.props.StringProperty(
        default="*.stl;",
        options={'HIDDEN'},
    )

    def invoke(self, context, event):
        # Call the "choose file" browser
        context.window_manager.fileselect_add(self)
        return {"RUNNING_MODAL"}

    def execute(self, context):
        # Explicit import_mesh call with self.filepath saved with invoked fileselect_add
        bpy.ops.import_mesh.stl(filepath=self.filepath)
        # Piece of code to be run AFTER import
        for obj in bpy.context.selected_objects:
            obj.name = "Bacon"
            obj.data.name = "Bacon"
        return {"FINISHED"}
    
    
class HelloWorldPanel(bpy.types.Panel):
    """Creates a Panel in the Object properties window"""
    bl_label = "Hello World Panel"
    bl_idname = "OBJECT_PT_hello"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "scene"

    def draw(self, context):
        layout = self.layout

        row = layout.row()
        row.operator("object.import_stl_custom")


def register():
    bpy.utils.register_class(HelloWorldPanel)
    bpy.utils.register_class(Import_STL_Custom)


def unregister():
    bpy.utils.unregister_class(HelloWorldPanel)
    bpy.utils.unregister_class(Import_STL_Custom)


if __name__ == "__main__":
    register()

See you ++
Tricotou

2 Likes

Thank You, know is working. I had to remove my addon, restart Blender, and after it, new button start working.
One more time, thanks for help.
Greets.