1
$\begingroup$

I'm writing an Add-on in which I create a new Collection and then invoke the ImportHelper to load an FBX file. After that I would like to process the loaded data. My Problem is, that my script doesn't wait until the ImportHelper is finished.

I defined the Import Helper like this:

class ImportFBXData(bpy.types.Operator, ImportHelper):
bl_idname = "import_fbx.read_data"  
bl_label = "Import FBX"

# ImportHelper mixin class uses this
filename_ext = ".fbx"

filter_glob: StringProperty(
    default="*.fbx",
    options={'HIDDEN'},
    maxlen=255,  
)

use_setting: BoolProperty(
)

def invoke(self, context, event):
    context.window_manager.fileselect_add(self)
    return {'RUNNING_MODAL'}

def execute(self, context):
    bpy.ops.import_scene.fbx(filepath = self.filepath)
    return {'FINISHED'}

I start this inside my Operator:

bpy.ops.import_fbx.read_data('INVOKE_DEFAULT')

Everything in front of this call gets executed properly. The File Browser comes up and I can select a file which is loaded properly. Because the File Browser runs modal, everything after it's call runs immediately but there is no data yet. How can I make the rest of the script to wait until I select a file, the FBX conversion is done and the data is loaded in to Blender?

I don't mind if the UI is locked up until the conversion is finished but I definitely need the file browser to select the FBX file.

$\endgroup$

1 Answer 1

1
$\begingroup$

The solution was very simple at the end. Everything what needs to be done with the data which was loaded by the ImportHelper should be part of the execute method of this class.

The invoke method (in my above script) was not needed at the end:

class ImportFBXData(Operator, ImportHelper):
    bl_idname = "import_fbx.read_data"  
    bl_label = "Import FBX"
    
    filter_glob: StringProperty(
        default='*.fbx',
        options={'HIDDEN'})
    
    def execute(self, context):
        # Everything what needs to be done before opening the file browser 
        new_fbx_collection = bpy.data.collections.new("New COllection")
        bpy.context.scene.collection.children.link(new_fbx_collection)

        # Open the File Browser and Import the FBX File
        filename, extension = os.path.splitext(self.filepath)
        bpy.ops.import_scene.fbx(filepath = self.filepath)
        
        # Everything what needs to be done after the file browser 
        ...
        obs = [o for o in bpy.data.collections[context.collection.name].all_objects if not o.parent and len(o.children)]
        for o in obs:
            ...
    return {'FINISHED'}

This way my Add-On works perfectly.

$\endgroup$
4
  • $\begingroup$ Hi. I have taken the liberty to edit your answer, corrected the code indentation and the context reference (bpy.context -> context) in order to make it a little clearer to future visitors. If you don't like my edit, just roll it back. Further reading: What do operator methods do? (poll, invoke, execute, draw & modal) Also note that according to PEP8 variable names should be lowercase: python.org/dev/peps/pep-0008/#function-and-variable-names hopefully nice to know... $\endgroup$
    – brockmann
    Feb 27, 2021 at 17:49
  • 1
    $\begingroup$ Thank you for the corrections! I really appreciate it! :-) As a beginner and without proper programming training it's very hard to write functioning code and such corrections help a lot to see my mistakes. (And hopefully learn from them... =) $\endgroup$
    – Steve
    Feb 27, 2021 at 18:36
  • $\begingroup$ The collection known as bpy.data.collections[context.collection.name] is context.collection which I assume the idea is to use new_fbx_collection so can simply use that reference. Re setting active collection blender.stackexchange.com/a/155433/15543 $\endgroup$
    – batFINGER
    Feb 27, 2021 at 20:34
  • $\begingroup$ You caught me... =) The part where it iterates on the objects, was the first part of my script and I copied it out from an internet example. The create collection part I made later and did not pay any attention to the copied code anymore. I changed it to obs = [o for o in bpy.data.collections[new_fbx_Collection].all_objects if not o.parent and len(o.children)] now. Many thanks for the suggestion! Dumb copying is the first step to learn but now I begin to understand the actual structure behind the copied lines. $\endgroup$
    – Steve
    Mar 1, 2021 at 11:29

You must log in to answer this question.

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