1
$\begingroup$

I'm using the fbx importer to import an fbx file and after the import is done I want to process the imported objects.

I need to open the importer window from bpy.ops.import_scene.fbx as I want to have access to all the fbx properties without having to hard-code my own duplicate of all the properties.

This seems to be quite complicated and I haven't found a good solution. Below is a method that seems to work but there is a few problems with it.

  1. What if the user press the "cancel" button? The modal operator is still running then.

  2. What if the fbx file can't be imported (corrupted file for example), the operator will still be running.

    import bpy
    from bpy_extras.io_utils import ImportHelper
    
    class ImporterFBX(bpy.types.Operator, ImportHelper):
        bl_idname = "importer.fbx"
        bl_label = "Import"
        bl_options = {'PRESET'}
    
        sceneobjects = 0
        currentobjects = 0
    
        def modal(self, context, event):
    
            # Objects imported, import done.
            if self.currentobjects > self.sceneobjects:
                return {'FINISHED'}
    
            self.currentobjects = len(bpy.data.objects)
    
            # Stop if esc is pressed.
            if event.type in {'ESC', 'RIGHTMOUSE'}:
                print("stopped")
                return{'CANCELLED'}
    
            # How to stop if the cancel button was pressed?
            # How to stop if an error occured?
    
            # Print the result if still running.        
            print("still running", event)
    
            return {'PASS_THROUGH'}
    
        def invoke(self, context, event):
            #save current number of objects on scene
            self.sceneobjects = len(bpy.data.objects)
    
            # Deselect everything.
            bpy.ops.object.select_all(action='DESELECT')
    
            #start the import
            bpy.ops.import_scene.fbx("INVOKE_REGION_WIN")
            context.window_manager.modal_handler_add(self)
            return {'RUNNING_MODAL'}
    
    def register():
        bpy.utils.register_class(ImporterFBX)
    
    
    if __name__ == "__main__":
        register()
    
        # Loop over a list of paths to fbx files and open the dialog window and process the result for each one of them. Every file might need to have different import properties. Below is just a quick example.
        for path in fbx_paths:
    
            # The above operator is called from another operator via:
            bpy.ops.importer.fbx("INVOKE_DEFAULT", filepath=path)
    
    
            # Get the result of import via selected objects.
            print(bpy.context.selected_objects)
    
            # Do other stuff...```
    
    
    
    
$\endgroup$
2
  • $\begingroup$ can you share a sample fbx file that creates a problem? $\endgroup$ Jan 22, 2023 at 6:30
  • $\begingroup$ You could just create an empty text file and rename that to fbx. The import will then fail and the modal operator is still running $\endgroup$ Jan 22, 2023 at 8:51

1 Answer 1

1
$\begingroup$

ImportHelper class has a built-in invoke() method called by bpy.ops.importer.fbx("INVOKE_DEFAULT") that opens the Filebrowser. No need to declare invoke() or modal() by yourself unless you want to tweak the Filebrowser. You need to insert an execute() method that is run by clicking the execute button and you can use cancel() when Filebrowser is aborted.

The Filebrowser is using some properties in the background always defined to keep user input. The selected directory is stored in self.filepath and need to be passed to the built-in import operator bpy.ops.import_scene.fbx(). To respond to corrupted files you can use try and except statements.

import bpy
from bpy_extras.io_utils import ImportHelper

class ImporterFBX(bpy.types.Operator, ImportHelper):
    bl_idname = "importer.fbx"
    bl_label = "Import"

    def execute(self, context):
        pre_objs = [o.name for o in bpy.data.objects]     # store objs before import

        try:
            bpy.ops.import_scene.fbx(filepath=self.filepath)  # try import fbx   

        except RuntimeError as ex:       # error
            print("! import corrupted")
            print(self.filepath)

        else:                            # post import things
            print(len(pre_objs), "objects before import")
            print(len(bpy.data.objects), "objects after import")
            for o in bpy.data.objects:                     
                if not o.name in pre_objs:
                    print("new:", o.name)
                
        return {'FINISHED'} 

    def cancel(self, context):
        print("import cancelled by user")

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

if __name__ == "__main__":
    register()
    bpy.ops.importer.fbx('INVOKE_DEFAULT')
$\endgroup$
1
  • 1
    $\begingroup$ Thanks for the reply @relaxed! Unfortunately it won't work as I need to use the built in dialog for the fbx importer to let the user select how to import the fbx. Otherwise I won't have access to all the properties without hard-coding a copy of all fbx properties. I realize my question could have been asked better, I'll try to edit it. $\endgroup$ Jan 22, 2023 at 16:12

You must log in to answer this question.

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