2
$\begingroup$

I am new to Blender and just started scripting for our pipeline. I have written a small script which when run sets up the scene unit settings. The script is run from a button in a panel.

To let the user know that the script has been run, a popup appears with a single "OK" button.

Whenever I click the button it closes Blender.

Edit: Blender also closes if I click elsewhere (not on the OK button)

Can anyone tell me why? Or tell me how to write this correctly?

Here's the code:

class SceneSettings(bpy.types.Operator):

  bl_idname = "la.scene_settings"
  bl_label = "Scene Settings Set Up"

  def execute(self, context):
    scene = bpy.context.scene
    scene.unit_settings.system = 'METRIC'
    scene.unit_settings.scale_length = 0.5
    context.window_manager.invoke_props_dialog(self,  width=175, height=50)
    return {'FINISHED'}

Thank you in advance,

Sofia

$\endgroup$
6
  • $\begingroup$ What do you need the dialog for? It doesn't seem to have any functionality. $\endgroup$
    – CodeManX
    Feb 9, 2015 at 13:21
  • $\begingroup$ I just want to let the user know that the script has been run, its more an information box than a dialog box. So all I want it a window with some text saying the script has run and an OK button to press to close the window. :) $\endgroup$ Feb 9, 2015 at 13:22
  • $\begingroup$ The user will need to click a button to run this operator, I see no reason why to confirm the execution with a dialog. You should use self.report(...) you if you really want to inform the user. BTW: Do you know that you can modify the startup.blend? You can activate the metric system there once and it will be used as default for all new files you create. $\endgroup$
    – CodeManX
    Feb 9, 2015 at 13:24
  • $\begingroup$ Thank you for the reply! I would very much like to have a pop up instead of self.report because the user may not have the "info" bar dragged down to see the output. I like to give feedback to the users - especially when the scripts get more complex - to inform them that the script had been run succesfully. I could write a script that opens a file on our network and saves it as the start up file, but then it will clear settings the user have already set. $\endgroup$ Feb 9, 2015 at 13:31
  • $\begingroup$ It doesn't need to be dragged down, self.report({'INFO'}, "Message") will display between the render engine dropdown and the version info, as long as the operator is executed in the context of the 3D View (button in T- or N-toolshelf or spacebar menu). $\endgroup$
    – CodeManX
    Feb 9, 2015 at 13:34

1 Answer 1

6
$\begingroup$

You seem to misunderstand how operators work. If there's supposed to be a props dialog, it is displayed before the operator execution. More specifically, in the invoke phase:

poll(cls, context) -> invoke(self, context, event) -> execute(self, context)

The poll classmethod of an operator is used to determine if the context allows the operator to run at all. If the context is not suitable (wrong area type, no object selected, ...), it needs to return False. You won't be able to run this operator until there's a valid context (not only from a button, but also spacebar menu and Python console). Operators in panels (=buttons) will be grayed out if polling fails.

What happens next depends on the execution context. If you run an operator from spacebar menu or by a button click, it will be usually INVOKE_DEFAULT and thus call invoke() of the operator. Notable about this method is, that an event object is passed to it. You need to return the result of wm.invoke_props_dialog(self) in invoke() to make the dialog work. It will open the dialog and wait for user input. If the user clicks outside the dialog, the operator will be aborted. If he/she clicks on OK, execute() will be called.

The execute() method of an operator contains the actual code of the operation. It is immediately executed if the execution context is DEFAULT_EXECUTE, which is the case for scripts and the Python console by default. There is usually no point in invoking the operator to get user input prior to the actual operation, and it's sometimes not even possible because of an incorrect context (an invocation from the Python console would run invoke() in the Python console, but a 3D View might be required). You would need to pass custom context along the execution context, like this:

bpy.ops.your.operator({'area': my_area}, 'INVOKE_DEFAULT')

Your operator does not define invoke(), therefore execute() is called immediately. The scene parameters are changed, but then you call the props dialog. It can't be used here and does crash for that reason. It is not supported to display a dialog after an action (operators supporting undo can display something in the redo panel, but that's about it).

class SceneSettings(bpy.types.Operator):

    bl_idname = "wm.scene_settings"
    bl_label = "Scene Settings Set Up"

    def invoke(self, context, event):
        wm = context.window_manager
        return wm.invoke_props_dialog(self, width=175, height=50)

    def execute(self, context):
        scene = context.scene
        scene.unit_settings.system = 'METRIC'
        scene.unit_settings.scale_length = 0.5
        return {'FINISHED'}

A more appropriate way to inform the user is to use self.report():

import bpy

class SceneSettings(bpy.types.Operator):

    bl_idname = "wm.scene_settings"
    bl_label = "Scene Settings Set Up"

    def execute(self, context):
        scene = context.scene
        scene.unit_settings.system = 'METRIC'
        scene.unit_settings.scale_length = 0.5
        self.report({'INFO'}, "Applied scene settings.")
        return {'FINISHED'}


def register():
    bpy.utils.register_module(__name__)

def unregister():
    bpy.utils.unregister_module(__name__)

if __name__ == "__main__":
    register()

Run this code in the Text Editor, then search for the operator in the 3D View spacebar menu.

self.report() in info area on operator execution in 3D View context

$\endgroup$
7
  • $\begingroup$ Thank you for your reply. I had a feeling I was misunderstanding the concept. Now I get it. Its unfortunate that you cannot have a dialog box after an operation is run. Now I will have to make sure all my coworkers have the info bar visible to them :) thank you again. $\endgroup$ Feb 9, 2015 at 13:51
  • $\begingroup$ what is "la" in "la.scene_settings" ? $\endgroup$
    – Chebhou
    Feb 9, 2015 at 13:55
  • $\begingroup$ Hmm that's very nice CoDEmanX - the screen short I mean. I wonder how to set that up as I dont have that showing at the moment. Its a great way to inform the user, I would never have thought of a pop up if I had known that was in the scene! Thank you for the screenshort:) Chebhou: its the initials of our production - it could have been anything. $\endgroup$ Feb 9, 2015 at 13:59
  • $\begingroup$ Apparently reports are not displayed in the header anymore according to this: developer.blender.org/T26708 $\endgroup$ Feb 9, 2015 at 14:06
  • $\begingroup$ you can use : bpy.context.window_manager.popup_menu(draw_menu, title ='Info',icon = 'INFO') with draw_menu(self, context) to show a message at the end $\endgroup$
    – Chebhou
    Feb 9, 2015 at 14:13

You must log in to answer this question.

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