Close/Confirm props dialog popup after string input with just one press of ENTER

Hi,
is there an elegant way to close/confirm a props popup dialog (after typing in a string/int/float into a field) with just one press of the enter button? Right now I need two presses of ENTER: the first to confirm the typed input in the field, the second to confirm the dialog.

Feel free to check out the problem yourself. Just run this script as an example, type in a number and get frustrated by the need of hitting enter two times to confirm:

import bpy

bl_info = {
    "name": "Test Add-on",
    "description": "This is just a test add-on.",
    "author": "Your Name Here",
    "version": (1, 0),
    "blender": (4, 0, 0),
    "category": "Object",
}

class Object_OT_Test_Addon(bpy.types.Operator):
    bl_idname = "object.test_addon"                     # Unique identifier for buttons and menu items to reference.
    bl_label = "My Test Add-on"                         # Display name for the interface (for example, in the menu).
    bl_options = {'REGISTER', 'UNDO'}                  # Register for the operator box & Enable for undo operation.
    bl_property = "dummy_input1"
    
    dummy_input1: bpy.props.IntProperty(name="Dummy Input 1", default=0, min=0, max=10)
    
    def invoke(self, context, event):

        # Now invoke the add-on popup
        return_code = context.window_manager.invoke_props_dialog(self)        

        return return_code

    def execute(self, context):
        
        ####################################################################################################

        # Add your code - the actual processing logic will go here.

        ####################################################################################################
        
        # Tell Blender that the operator finished successfully.
        return {'FINISHED'}

def menu_func(self, context):
    self.layout.operator(Object_OT_Test_Addon.bl_idname)

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

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

# This allows you to run the script directly from Blender's Text editor
# to test the add-on without having to install it.
if __name__ == "__main__":
    register()
    
    bpy.ops.object.test_addon('INVOKE_DEFAULT')

The context: I am working on a small plugin, which’s only purpose is to speed up the workflow:

  1. Hitting a hotkey to invoke the plugin and opening the popup dialog, the focus is already in the input field using bl_property
  2. Typing in the desired number
  3. Hitting ENTER to confirm an close the popup

But step 3 requires hitting ENTER two times at the moment, because still the cursor is in the input field. As I said, you first have to confirm the input by hitting enter and THEN there is the possibility to confirm the dialog by hitting enter once again.

Is there a hassle-free way to code that the hit of enter confirms the popup and the dialog at once? Or maybe a props dialog popup is just not the best way to achieve this? Maybe another UI solution would do what I want?

Thanks for your help already

WindowManager(ID) - Blender Python API

classmethod invoke_props_popup(operator, event )#

Operator popup invoke (show operator properties and execute it automatically on changes)

classmethod invoke_props_dialog(operator, ***, width=300, title=‘’, confirm_text=‘’, cancel_default=False, text_ctxt=‘’, translate=True )#

Operator dialog (non-autoexec popup) invoke (show operator properties and only execute it on click on OK button)

python - Close a popup with an OP call - Blender Stack Exchange

import bpy

bl_info = {
    "name": "Test Add-on",
    "description": "This is just a test add-on.",
    "author": "Your Name Here",
    "version": (1, 0),
    "blender": (4, 0, 0),
    "category": "Object",
}

class Object_OT_Test_Addon(bpy.types.Operator):
    bl_idname = "object.test_addon"
    bl_label = "My Test Add-on"
    bl_options = {'REGISTER', 'UNDO'}
    bl_property = "dummy_input1"
    
    dummy_input1: bpy.props.IntProperty(name="Dummy Input 1", default=0, min=0, max=10)
    mouse_x: bpy.props.IntProperty(default=0)
    mouse_y: bpy.props.IntProperty(default=0)
    
    def draw(self, context):
        layout = self.layout
        layout.prop(self, "dummy_input1")
    
    def invoke(self, context, event):
        self.mouse_x = event.mouse_x
        self.mouse_y = event.mouse_y
        return context.window_manager.invoke_props_popup(self, None)

    def close_panel(self, context):
        window = context.window
        offset = 310
        x, y = self.mouse_x, self.mouse_y
        window.cursor_warp(x + offset, y + offset)
        def restore_mouse_position():
            window.cursor_warp(x, y)
            bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1)

    def execute(self, context):
        self.close_panel(context)
        return {'FINISHED'}

def menu_func(self, context):
    self.layout.operator(Object_OT_Test_Addon.bl_idname)

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

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

if __name__ == "__main__":
    register()
    
    bpy.ops.object.test_addon('INVOKE_DEFAULT')
1 Like

ok, that’s cool too