bugfix [#24466] Selecting of object with pattern leads to strange behavior
authorCampbell Barton <ideasman42@gmail.com>
Sun, 31 Oct 2010 14:43:30 +0000 (14:43 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Sun, 31 Oct 2010 14:43:30 +0000 (14:43 +0000)
The undo problem was caused by python operators returning 'RUNNING_MODAL' rather then the return value from wm.invoke_props_popup(self, event) - 'FINISHED'.

This was done because returning FINISHED would free the operator causing the buttons redo handler to try and run a freed operator and crash.

So the real fix is to disallow any operators to use wm.invoke_props_popup(self, event) if they dont have the REGISTER option enabled, fixing the crash and redo problem.

release/scripts/op/object.py
release/scripts/op/presets.py
release/scripts/op/wm.py
source/blender/windowmanager/intern/wm_event_system.c
source/blender/windowmanager/intern/wm_operators.c

index 8dd55fc5b9222e1453e6c9b963a341d3d08d97b6..b5c46c757b3f192b55fac48896f4cc2a7df1c584 100644 (file)
@@ -60,9 +60,7 @@ class SelectPattern(bpy.types.Operator):
 
     def invoke(self, context, event):
         wm = context.window_manager
-        # return wm.invoke_props_popup(self, event)
-        wm.invoke_props_popup(self, event)
-        return {'RUNNING_MODAL'}
+        return wm.invoke_props_popup(self, event)
 
     def draw(self, context):
         layout = self.layout
index 2f6a5b69c20f19bf535942d63574a50ff97a131d..ec14e305c51fd1ae47fee1c10f6589e6b7c59542 100644 (file)
@@ -29,6 +29,7 @@ class AddPresetBase():
      - preset_subdir '''
     # bl_idname = "script.preset_base_add"
     # bl_label = "Add a Python Preset"
+    bl_options = {'REGISTER'} # only because invoke_props_popup requires.
 
     name = bpy.props.StringProperty(name="Name", description="Name of the preset, used to make the path name", maxlen=64, default="")
     remove_active = bpy.props.BoolProperty(default=False, options={'HIDDEN'})
@@ -110,11 +111,7 @@ class AddPresetBase():
     def invoke(self, context, event):
         if not self.remove_active:
             wm = context.window_manager
-            #crashes, TODO - fix
-            #return wm.invoke_props_popup(self, event)
-
-            wm.invoke_props_popup(self, event)
-            return {'RUNNING_MODAL'}
+            return wm.invoke_props_popup(self, event)
         else:
             return self.execute(context)
 
index de2403a773f8c587ff1a286911eade164c14006e..ca1ed6ed168cf3b441411b0fc310a1a410024656 100644 (file)
@@ -661,6 +661,7 @@ class WM_OT_properties_edit(bpy.types.Operator):
     '''Internal use (edit a property data_path)'''
     bl_idname = "wm.properties_edit"
     bl_label = "Edit Property"
+    bl_options = {'REGISTER'} # only because invoke_props_popup requires.
 
     data_path = rna_path
     property = rna_property
@@ -721,11 +722,7 @@ class WM_OT_properties_edit(bpy.types.Operator):
             self.description = prop_ui.get("description", "")
 
         wm = context.window_manager
-        # This crashes, TODO - fix
-        #return wm.invoke_props_popup(self, event)
-
-        wm.invoke_props_popup(self, event)
-        return {'RUNNING_MODAL'}
+        return wm.invoke_props_popup(self, event)
 
 
 class WM_OT_properties_add(bpy.types.Operator):
index 47ca4314cc7ee97dd1e004bb93ec393cbc67690e..4eba45c61b9fccbd16e429e0e9845ae6cb139ca3 100644 (file)
@@ -364,9 +364,9 @@ int WM_operator_poll(bContext *C, wmOperatorType *ot)
        wmOperatorTypeMacro *otmacro;
        
        for(otmacro= ot->macro.first; otmacro; otmacro= otmacro->next) {
-               wmOperatorType *ot= WM_operatortype_find(otmacro->idname, 0);
+               wmOperatorType *ot_macro= WM_operatortype_find(otmacro->idname, 0);
                
-               if(0==WM_operator_poll(C, ot))
+               if(0==WM_operator_poll(C, ot_macro))
                        return 0;
        }
        
index ccdb19adfced89be9e8057df9aaa2d976e201d2a..2a9ef1e752e59f18fe900c14065342ad9fd5615f 100644 (file)
@@ -31,6 +31,7 @@
 #include <ctype.h>
 #include <stdio.h>
 #include <stddef.h>
+#include <assert.h>
 #ifdef WIN32
 #include <windows.h>
 #include <io.h>
@@ -889,6 +890,11 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op)
        block= uiBeginBlock(C, ar, "redo_popup", UI_EMBOSS);
        uiBlockClearFlag(block, UI_BLOCK_LOOP);
        uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN|UI_BLOCK_RET_1|UI_BLOCK_MOVEMOUSE_QUIT);
+
+       /* if register is not enabled, the operator gets freed on OPERATOR_FINISHED
+        * ui_apply_but_funcs_after calls redo_cb and crashes */
+       assert(op->type->flag & OPTYPE_REGISTER);
+
        uiBlockSetHandleFunc(block, redo_cb, arg_op);
 
        if(!op->properties) {
@@ -1021,6 +1027,11 @@ int WM_operator_props_popup(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
 {
        int retval= OPERATOR_CANCELLED;
        
+       if((op->type->flag & OPTYPE_REGISTER)==0) {
+               BKE_reportf(op->reports, RPT_ERROR, "Operator '%s' does not have register enabled, incorrect invoke function.", op->type->idname);
+               return OPERATOR_CANCELLED;
+       }
+       
        if(op->type->exec) {
                retval= op->type->exec(C, op);
 
@@ -1059,6 +1070,11 @@ int WM_operator_ui_popup(bContext *C, wmOperator *op, int width, int height)
 
 int WM_operator_redo_popup(bContext *C, wmOperator *op)
 {
+       if((op->type->flag & OPTYPE_REGISTER)==0) {
+               BKE_reportf(op->reports, RPT_ERROR, "Operator '%s' does not have register enabled, incorrect invoke function.", op->type->idname);
+               return OPERATOR_CANCELLED;
+       }
+       
        uiPupBlock(C, wm_block_create_redo, op);
 
        return OPERATOR_CANCELLED;