bugfix [#24466] Selecting of object with pattern leads to strange behavior
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.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user