0
$\begingroup$

When the ImportHelper helper class is inserted into an operator by default, the operator opens a popup with the File Browser window.

Now the question is this, I would like to keep an operator who works in 2 ways, 1 is the one in which a Browser opens for me and the other, is the one that does not open a browser and executes my code.

I'll give an example to explain even better:

class ImportSomeData(Operator, ImportHelper):
    
    bl_idname = "import.test"
    bl_label = "Import Some Data"

    open_file_browser: BoolProperty(default=True)
    file: StringProperty()
    
    filter_glob: StringProperty(options={'HIDDEN'}, default='*.jpg;*.jpeg;*.png;*.bmp')

    def execute(self, context):
        if self.open_file_browser:
            # Choose file from File Browser:
            my_file = self.filepath
        else:
            # Choose the file from a known path: 
            my_file = self.file
        
        if os.path.isfile(my_file):
            bpy.data.images.load(my_file)
            
        return {'FINISHED'}
    

class LayoutDemoPanel(bpy.types.Panel):
    bl_label = "Layout Demo"
    bl_idname = "SCENE_PT_layout"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "scene"

    def draw(self, context):
        
        layout = self.layout
        
        # Button 1:
        # Import file from File Browser:
        ops = layout.operator("import.test", text="Load")
        ops.open_file_browser = True
        
        # Button 2        
        # Import file from a known path:
        ops = layout.operator("import.test", text="Load")
        ops.open_file_browser = True
        ops.file = "c:\\my_file_path\\my_file.jpg"
$\endgroup$
1
  • 2
    $\begingroup$ By the time the code reaches execute it's already too late, the file browser is open. You have to use the invoke method and switch there $\endgroup$
    – Gorgious
    Oct 8, 2022 at 17:04

1 Answer 1

1
+50
$\begingroup$

As @Gorgious stated, the invoke method is the place to make the switch: open the file browser or not? But when you call the execute method in the invoke method, the file browser isn't opened automatically, so the extra trick is to bind the file selector within the invoke a second time with context.window_manager.fileselect_add(self) (see Blender docs).

Entire code:

import bpy
from bpy.types import Operator
from bpy.props import BoolProperty, StringProperty
from bpy_extras.io_utils import ImportHelper
import os


class ImportSomeData(Operator, ImportHelper):
    
    bl_idname = "import.test"
    bl_label = "Import Some Data"

    open_file_browser: BoolProperty(default=True, options={'HIDDEN'})
    file: StringProperty(options={'HIDDEN'})
    
    filter_glob: StringProperty(options={'HIDDEN'}, default='*.jpg;*.jpeg;*.png;*.bmp')
    
    
    # Operator is called, but not executed yet
    def invoke(self, context, event):
        # Choose image file in File browser?
        if self.open_file_browser:
            # Open File browser
            # See: https://docs.blender.org/api/current/bpy.types.WindowManager.html#bpy.types.WindowManager.fileselect_add
            context.window_manager.fileselect_add(self)
            return {'RUNNING_MODAL'}
        else:
            # Do not open File browser, perform operator immediately
            return self.perform_operator()
    
    
    # User has selected an image in the File browser
    def execute(self, context):
        self.file = self.filepath
        return self.perform_operator()
    
    
    # Perform operator: load image
    def perform_operator(self):
        if os.path.isfile(self.file):
            bpy.data.images.load(self.file)
        return {'FINISHED'}
    

class LayoutDemoPanel(bpy.types.Panel):
    bl_label = "Layout Demo"
    bl_idname = "SCENE_PT_layout"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "scene"

    def draw(self, context):
        
        layout = self.layout
        
        # Button 1:
        # Import file from File Browser:
        ops = layout.operator("import.test", text="Load")
        ops.open_file_browser = True
        
        # Button 2        
        # Import file from a known path:
        ops = layout.operator("import.test", text="Load")
        ops.open_file_browser = False
        ops.file = "c:\\my_file_path\\my_file.jpg"


def register():
    bpy.utils.register_class(LayoutDemoPanel)
    bpy.utils.register_class(ImportSomeData)


def unregister():
    bpy.utils.unregister_class(LayoutDemoPanel)
    bpy.utils.unregister_class(ImportSomeData)
    

if __name__ == "__main__":
    register()
$\endgroup$
1
  • $\begingroup$ This is the solution, work fine 👍 $\endgroup$
    – Noob Cat
    Nov 1, 2022 at 12:19

You must log in to answer this question.

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