14
$\begingroup$

I have a button in my menu named "New File" as shown:

enter image description here

and I want when I click on the "New File" button to imitate what the Blender File->New does, where a check message box appear first confirming that you want to reload the Start-up File and if pressed then the startup file is loaded as shown below.

enter image description here

This is my script, when I press on new it opens the startup file without checking:

class NewFile(bpy.types.Operator):
    """New File"""
    bl_idname = "wm.newfile"  
    bl_label = "New File"
    bl_options = {'REGISTER', 'UNDO'}

    def execute(self, context):
        bpy.ops.wm.read_homefile()
        return {"FINISHED"} 
$\endgroup$
3
  • $\begingroup$ My Python isn't the greatest, but this seems to work with wm.open_mainfile and wm.read_homefile. I tested with the ui panel template though, I hadn't seen your edit. $\endgroup$ Commented Feb 9, 2017 at 5:54
  • $\begingroup$ @Timaroberts no it doesn't show the checking message $\endgroup$
    – Tak
    Commented Feb 9, 2017 at 12:08
  • 1
    $\begingroup$ @poor thank you so much my friend, very detailed and beneficial (Y) :) $\endgroup$
    – Tak
    Commented Feb 13, 2017 at 22:51

1 Answer 1

45
$\begingroup$

When calling an operator via bpy.ops.* without any execution context the execute() method of the respective operator runs by default. If the operator provides any kind of 'user interaction' like a 'confirmation dialog' in this case, then you can pass 'INVOKE_DEFAULT' as execution context when calling the operator which will also run its invoke() method:

bpy.ops.wm.read_homefile('INVOKE_DEFAULT')

enter image description here

In order to display the operator as a button and also 'enable' its user interaction, you have to set the operator_context in the 'layout' before calling the operator:

enter image description here

Blender 2.7x

import bpy

class HelloWorldPanel(bpy.types.Panel):
    """Creates a Panel in the Object properties window"""
    bl_idname = "CUSTOM_my_panel"
    bl_label = "My Panel"
    bl_space_type = "VIEW_3D"
    bl_region_type = "TOOLS"
    bl_category = "Tools"

    def draw(self, context):
        layout = self.layout
        layout.operator_context = 'INVOKE_DEFAULT' #'INVOKE_AREA'
        layout.operator("wm.read_homefile", text="New", icon='NEW')

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

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

if __name__ == "__main__":
    register()

Blender 2.8x and beyond

class OBJECT_PT_CustomPanel(bpy.types.Panel):
    bl_label = "My Panel"
    bl_idname = "OBJECT_PT_custom_panel"
    bl_space_type = "VIEW_3D"   
    bl_region_type = "UI"
    bl_category = "Tools"
    bl_context = "objectmode"

    def draw(self, context):
        layout = self.layout
        layout.operator_context = 'INVOKE_DEFAULT' #'INVOKE_AREA'
        layout.operator("wm.read_homefile", text="New", icon='FILE_NEW')

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

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

if __name__ == "__main__":
    register()

Custom Confirm Dialog

For a custom conformation dialog you can wrap the operator into another one and invoke invoke_confirm(operator, event) classmethod of the window-manager to confirm the execution by the user.

enter image description here

Blender 2.7x

import bpy

class SimpleConfirmOperator(bpy.types.Operator):
    """Really?"""
    bl_idname = "my_category.custom_confirm_dialog"
    bl_label = "Do you really want to do that?"
    bl_options = {'REGISTER', 'INTERNAL'}
    
    @classmethod
    def poll(cls, context):
        return True
    
    def execute(self, context):
        self.report({'INFO'}, "YES!")
        return {'FINISHED'}

    def invoke(self, context, event):
        return context.window_manager.invoke_confirm(self, event)

class HelloWorldPanel(bpy.types.Panel):
    """Creates a Panel in the Object properties window"""
    bl_idname = "CUSTOM_my_panel"
    bl_label = "My Panel"
    bl_space_type = "VIEW_3D"
    bl_region_type = "TOOLS"
    bl_category = "Tools"

    def draw(self, context):
        layout = self.layout
        layout.operator(SimpleConfirmOperator.bl_idname)

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

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

if __name__ == "__main__":
    register()

Blender 2.8x and beyond

import bpy

class SimpleConfirmOperator(bpy.types.Operator):
    """Really?"""
    bl_idname = "my_category.custom_confirm_dialog"
    bl_label = "Do you really want to do that?"
    bl_options = {'REGISTER', 'INTERNAL'}

    @classmethod
    def poll(cls, context):
        return True

    def execute(self, context):
        self.report({'INFO'}, "YES!")
        return {'FINISHED'}

    def invoke(self, context, event):
        return context.window_manager.invoke_confirm(self, event)
    

class OBJECT_PT_CustomPanel(bpy.types.Panel):
    bl_label = "My Panel"
    bl_idname = "OBJECT_PT_custom_panel"
    bl_space_type = "VIEW_3D"   
    bl_region_type = "UI"
    bl_category = "Tools"
    bl_context = "objectmode"

    def draw(self, context):
        layout = self.layout
        layout.operator(SimpleConfirmOperator.bl_idname)

def register():
    bpy.utils.register_class(OBJECT_PT_CustomPanel)
    bpy.utils.register_class(SimpleConfirmOperator)

def unregister():
    bpy.utils.unregister_class(SimpleConfirmOperator)
    bpy.utils.unregister_class(OBJECT_PT_CustomPanel)

if __name__ == "__main__":
    register()

Property Confirm

In order to display a popup, some properties and an OK 'button' you can return wm.invoke_props_dialog(self) instead:

enter image description here

Blender 2.7x

import bpy

class SimplePropConfirmOperator(bpy.types.Operator):
    """Really?"""
    bl_idname = "my_category.custom_confirm_dialog"
    bl_label = "Do you really want to do that?"
    bl_options = {'REGISTER', 'INTERNAL'}
    
    prop1 = bpy.props.BoolProperty()
    prop2 = bpy.props.BoolProperty()
    
    @classmethod
    def poll(cls, context):
        return True

    def execute(self, context):
        self.report({'INFO'}, "YES!")
        return {'FINISHED'}

    def invoke(self, context, event):
        return context.window_manager.invoke_props_dialog(self)

    def draw(self, context):
        row = self.layout
        row.prop(self, "prop1", text="Property A")
        row.prop(self, "prop2", text="Property B")
        
        
class HelloWorldPanel(bpy.types.Panel):
    """Creates a Panel in the Object properties window"""
    bl_idname = "CUSTOM_my_panel"
    bl_label = "My Panel"
    bl_space_type = "VIEW_3D"
    bl_region_type = "TOOLS"
    bl_category = "Tools"

    def draw(self, context):
        layout = self.layout
        layout.operator(SimplePropConfirmOperator.bl_idname)

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

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

if __name__ == "__main__":
    register()

Blender 2.8x and beyond

import bpy

class SimplePropConfirmOperator(bpy.types.Operator):
    """Really?"""
    bl_idname = "my_category.custom_confirm_dialog"
    bl_label = "Do you really want to do that?"
    bl_options = {'REGISTER', 'INTERNAL'}

    prop1: bpy.props.BoolProperty()
    prop2: bpy.props.BoolProperty()

    @classmethod
    def poll(cls, context):
        return True

    def execute(self, context):
        self.report({'INFO'}, "YES!")
        return {'FINISHED'}

    def invoke(self, context, event):
        return context.window_manager.invoke_props_dialog(self)

    def draw(self, context):
        row = self.layout
        row.prop(self, "prop1", text="Property A")
        row.prop(self, "prop2", text="Property B")
    

class OBJECT_PT_CustomPanel(bpy.types.Panel):
    bl_label = "My Panel"
    bl_idname = "OBJECT_PT_custom_panel"
    bl_space_type = "VIEW_3D"   
    bl_region_type = "UI"
    bl_category = "Tools"
    bl_context = "objectmode"

    def draw(self, context):
        layout = self.layout
        layout.operator(SimplePropConfirmOperator.bl_idname)

def register():
    bpy.utils.register_class(OBJECT_PT_CustomPanel)
    bpy.utils.register_class(SimplePropConfirmOperator)

def unregister():
    bpy.utils.unregister_class(SimplePropConfirmOperator)
    bpy.utils.unregister_class(OBJECT_PT_CustomPanel)

if __name__ == "__main__":
    register()

Simple Popup

For the sake of completeness, you can also display a popup without any OK button by using wm.invoke_popup(self):

import bpy

class SimplePopUpOperator(bpy.types.Operator):
    """Really?"""
    bl_idname = "my_category.custom_popup_dialog"
    bl_label = "Do you really want to do that?"
    bl_options = {'REGISTER', 'INTERNAL'}

    prop1: bpy.props.BoolProperty()
    prop2: bpy.props.BoolProperty()

    @classmethod
    def poll(cls, context):
        return True

    def execute(self, context):
        self.report({'INFO'}, "YES!")
        return {'FINISHED'}

    def invoke(self, context, event):
        return context.window_manager.invoke_popup(self)

    def draw(self, context):
        row = self.layout
        row.label(text="Do you really want to do that?")
        row.prop(self, "prop1", text="Property A")
        row.prop(self, "prop2", text="Property B")


class OBJECT_PT_CustomPanel(bpy.types.Panel):
    bl_label = "My Panel"
    bl_idname = "OBJECT_PT_custom_panel"
    bl_space_type = "VIEW_3D"   
    bl_region_type = "UI"
    bl_category = "Tools"
    bl_context = "objectmode"

    def draw(self, context):
        layout = self.layout
        layout.operator(SimplePopUpOperator.bl_idname)

def register():
    bpy.utils.register_class(OBJECT_PT_CustomPanel)
    bpy.utils.register_class(SimplePopUpOperator)

def unregister():
    bpy.utils.unregister_class(SimplePropConfirmOperator)
    bpy.utils.unregister_class(SimplePopUpOperator)

if __name__ == "__main__":
    register()

Note: bl_options of both examples are set to 'INTERNAL' which excludes the operators from search results, remove it if you'd like to run the operator via space bar/F3.

$\endgroup$
2
  • $\begingroup$ Is it possible to create a dialog working similar to this, but in the style of the 2.80 save prompt from Python? $\endgroup$
    – Ray
    Commented Mar 5, 2020 at 20:30
  • $\begingroup$ invoke_props_dialog, see the last example or all draw methods here. file dialog is written in C @Ray $\endgroup$
    – p2or
    Commented Mar 6, 2020 at 13:51

You must log in to answer this question.

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