diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 011259dd959..ef4398608d1 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -222,7 +222,7 @@ static void ui_apply_but_funcs_after(bContext *C) after->butm_func(C, after->butm_func_arg, after->a2); if(after->opname) - WM_operator_name_call(C, after->opname, after->opcontext, after->opptr, NULL); + WM_operator_name_call(C, after->opname, after->opcontext, after->opptr); if(after->opptr) { WM_operator_properties_free(after->opptr); MEM_freeN(after->opptr); diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 0d8a56ad728..e9ef10648e9 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -1693,7 +1693,7 @@ static void operator_cb(bContext *C, void *arg, int retval) const char *opname= arg; if(opname && retval > 0) - WM_operator_name_call(C, opname, WM_OP_EXEC_DEFAULT, NULL, NULL); + WM_operator_name_call(C, opname, WM_OP_EXEC_DEFAULT, NULL); } static void vconfirm(bContext *C, char *opname, char *title, char *itemfmt, va_list ap) diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index 7804f698c9b..997e1f55967 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -76,7 +76,7 @@ static int mesh_add_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *event { mesh_add_duplicate_exec(C, op); RNA_int_set(op->ptr, "mode", TFM_TRANSLATION); - WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr, NULL); + WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index fb4e50ab4ab..f213e4f9cac 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -5784,7 +5784,7 @@ static int add_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *event) add_duplicate_exec(C, op); RNA_int_set(op->ptr, "mode", TFM_TRANSLATION); - WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr, NULL); + WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_action/action_header.c b/source/blender/editors/space_action/action_header.c index 65a2d956e11..2695f77e902 100644 --- a/source/blender/editors/space_action/action_header.c +++ b/source/blender/editors/space_action/action_header.c @@ -1543,10 +1543,10 @@ static void do_action_buttons(bContext *C, void *arg, int event) break; case B_ACTCOPYKEYS: - WM_operator_name_call(C, "ACT_OT_keyframes_copy", WM_OP_EXEC_REGION_WIN, NULL, NULL); + WM_operator_name_call(C, "ACT_OT_keyframes_copy", WM_OP_EXEC_REGION_WIN, NULL); break; case B_ACTPASTEKEYS: - WM_operator_name_call(C, "ACT_OT_keyframes_paste", WM_OP_EXEC_REGION_WIN, NULL, NULL); + WM_operator_name_call(C, "ACT_OT_keyframes_paste", WM_OP_EXEC_REGION_WIN, NULL); break; } } diff --git a/source/blender/editors/space_node/node_header.c b/source/blender/editors/space_node/node_header.c index 6883affe0b2..d239ebea472 100644 --- a/source/blender/editors/space_node/node_header.c +++ b/source/blender/editors/space_node/node_header.c @@ -75,7 +75,7 @@ static void do_node_selectmenu(bContext *C, void *arg, int event) switch(event) { case 1: /* border select */ - WM_operator_name_call(C, "NODE_OT_border_select", WM_OP_INVOKE_REGION_WIN, NULL, NULL); + WM_operator_name_call(C, "NODE_OT_border_select", WM_OP_INVOKE_REGION_WIN, NULL); break; case 2: /* select/deselect all */ // XXX node_deselectall(snode, 1); @@ -591,13 +591,13 @@ static void do_node_viewmenu(bContext *C, void *arg, int event) switch(event) { case 1: /* Zoom in */ - WM_operator_name_call(C, "View2D_OT_view_zoomin", WM_OP_EXEC_REGION_WIN, NULL, NULL); + WM_operator_name_call(C, "View2D_OT_view_zoomin", WM_OP_EXEC_REGION_WIN, NULL); break; case 2: /* View all */ - WM_operator_name_call(C, "View2D_OT_view_zoomout", WM_OP_EXEC_REGION_WIN, NULL, NULL); + WM_operator_name_call(C, "View2D_OT_view_zoomout", WM_OP_EXEC_REGION_WIN, NULL); break; case 3: /* View all */ - WM_operator_name_call(C, "NODE_OT_fit_all", WM_OP_EXEC_REGION_WIN, NULL, NULL); + WM_operator_name_call(C, "NODE_OT_fit_all", WM_OP_EXEC_REGION_WIN, NULL); break; case 4: /* Grease Pencil */ // XXX add_blockhandler(sa, NODES_HANDLER_GREASEPENCIL, UI_PNL_UNSTOW); diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index 71824b477ba..7d3ae203cd2 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -141,9 +141,9 @@ static int retopo_mesh_paint_check() {return 0;} void ED_view3d_exit_paint_modes(bContext *C) { if(G.f & G_VERTEXPAINT) - WM_operator_name_call(C, "VIEW3D_OT_vpaint_toggle", WM_OP_EXEC_REGION_WIN, NULL, NULL); + WM_operator_name_call(C, "VIEW3D_OT_vpaint_toggle", WM_OP_EXEC_REGION_WIN, NULL); else if(G.f & G_WEIGHTPAINT) - WM_operator_name_call(C, "VIEW3D_OT_wpaint_toggle", WM_OP_EXEC_REGION_WIN, NULL, NULL); + WM_operator_name_call(C, "VIEW3D_OT_wpaint_toggle", WM_OP_EXEC_REGION_WIN, NULL); // if(G.f & G_TEXTUREPAINT) set_texturepaint(); // if(G.f & G_SCULPTMODE) set_sculptmode(); @@ -465,7 +465,7 @@ static void do_view3d_view_alignviewmenu(bContext *C, void *arg, int event) // XXX mainqenter(PADASTERKEY, 1); break; case 6: /* Center View and Cursor to Origin */ - WM_operator_name_call(C, "VIEW3D_OT_viewcenter", WM_OP_EXEC_REGION_WIN, NULL, NULL); + WM_operator_name_call(C, "VIEW3D_OT_viewcenter", WM_OP_EXEC_REGION_WIN, NULL); curs= give_cursor(scene, v3d); curs[0]=curs[1]=curs[2]= 0.0; break; @@ -550,10 +550,10 @@ static void do_view3d_viewmenu(bContext *C, void *arg, int event) endlocalview(scene, sa); break; case 9: /* View All (Home) */ - WM_operator_name_call(C, "VIEW3D_OT_viewhome", WM_OP_EXEC_REGION_WIN, NULL, NULL); + WM_operator_name_call(C, "VIEW3D_OT_viewhome", WM_OP_EXEC_REGION_WIN, NULL); break; case 11: /* View Selected */ - WM_operator_name_call(C, "VIEW3D_OT_viewcenter", WM_OP_EXEC_REGION_WIN, NULL, NULL); + WM_operator_name_call(C, "VIEW3D_OT_viewcenter", WM_OP_EXEC_REGION_WIN, NULL); break; case 13: /* Play Back Animation */ play_anim(0); @@ -565,7 +565,7 @@ static void do_view3d_viewmenu(bContext *C, void *arg, int event) add_blockhandler(sa, VIEW3D_HANDLER_PROPERTIES, UI_PNL_UNSTOW); break; case 17: /* Set Clipping Border */ - WM_operator_name_call(C, "VIEW3D_OT_clipping", WM_OP_INVOKE_REGION_WIN, NULL, NULL); + WM_operator_name_call(C, "VIEW3D_OT_clipping", WM_OP_INVOKE_REGION_WIN, NULL); break; case 18: /* render preview */ toggle_blockhandler(sa, VIEW3D_HANDLER_PREVIEW, 0); @@ -5333,7 +5333,7 @@ static void do_view3d_buttons(bContext *C, void *arg, int event) switch(event) { case B_HOME: - WM_operator_name_call(C, "VIEW3D_OT_viewhome", WM_OP_EXEC_REGION_WIN, NULL, NULL); + WM_operator_name_call(C, "VIEW3D_OT_viewhome", WM_OP_EXEC_REGION_WIN, NULL); break; case B_REDR: ED_area_tag_redraw(sa); @@ -5403,7 +5403,7 @@ static void do_view3d_buttons(bContext *C, void *arg, int event) ED_view3d_exit_paint_modes(C); if(obedit) ED_object_exit_editmode(C, EM_FREEUNDO|EM_FREEUNDO|EM_WAITCURSOR); /* exit editmode and undo */ - WM_operator_name_call(C, "SCULPT_OT_toggle_mode", WM_OP_EXEC_REGION_WIN, NULL, NULL); + WM_operator_name_call(C, "SCULPT_OT_toggle_mode", WM_OP_EXEC_REGION_WIN, NULL); } } else if (v3d->modeselect == V3D_VERTEXPAINTMODE_SEL) { @@ -5412,7 +5412,7 @@ static void do_view3d_buttons(bContext *C, void *arg, int event) ED_view3d_exit_paint_modes(C); if(obedit) ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* exit editmode and undo */ - WM_operator_name_call(C, "VIEW3D_OT_vpaint_toggle", WM_OP_EXEC_REGION_WIN, NULL, NULL); + WM_operator_name_call(C, "VIEW3D_OT_vpaint_toggle", WM_OP_EXEC_REGION_WIN, NULL); } } else if (v3d->modeselect == V3D_TEXTUREPAINTMODE_SEL) { @@ -5431,7 +5431,7 @@ static void do_view3d_buttons(bContext *C, void *arg, int event) if(obedit) ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* exit editmode and undo */ - WM_operator_name_call(C, "VIEW3D_OT_wpaint_toggle", WM_OP_EXEC_REGION_WIN, NULL, NULL); + WM_operator_name_call(C, "VIEW3D_OT_wpaint_toggle", WM_OP_EXEC_REGION_WIN, NULL); } } else if (v3d->modeselect == V3D_POSEMODE_SEL) { diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c index f800b7d0d04..fb1040fac18 100644 --- a/source/blender/python/intern/bpy_operator.c +++ b/source/blender/python/intern/bpy_operator.c @@ -194,6 +194,11 @@ static PyObject * pyop_func_call(BPy_OperatorFunc * self, PyObject *args, PyObje return NULL; } + if(ot->poll && (ot->poll(self->C) == 0)) { + PyErr_SetString( PyExc_SystemError, "Operator poll() function failed, context is incorrect"); + return NULL; + } + WM_operator_properties_create(&ptr, self->name); error_val= PYOP_props_from_dict(&ptr, kw); @@ -203,7 +208,7 @@ static PyObject * pyop_func_call(BPy_OperatorFunc * self, PyObject *args, PyObje BKE_reports_init(&reports, RPT_STORE); - WM_operator_name_call(self->C, self->name, WM_OP_EXEC_DEFAULT, &ptr, &reports); + WM_operator_call_py(self->C, ot, &ptr, &reports); report_str= BKE_reports_string(&reports, RPT_ERROR); diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index a7b90a7fccd..d7559eac306 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -126,7 +126,8 @@ void WM_operatortype_append_ptr (void (*opfunc)(wmOperatorType*, void *), void int WM_operatortype_remove(const char *idname); int WM_operator_call (struct bContext *C, struct wmOperator *op); -int WM_operator_name_call (struct bContext *C, const char *opstring, int context, struct PointerRNA *properties, struct ReportList *reports); +int WM_operator_name_call (struct bContext *C, const char *opstring, int context, struct PointerRNA *properties); +int WM_operator_call_py(struct bContext *C, struct wmOperatorType *ot, struct PointerRNA *properties, struct ReportList *reports); void WM_operator_properties_create(struct PointerRNA *ptr, const char *opstring); void WM_operator_properties_free(struct PointerRNA *ptr); diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index a9069abe113..0f2df53481f 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -440,41 +440,49 @@ int WM_operator_call(bContext *C, wmOperator *op) return retval; } -static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, PointerRNA *properties, ReportList *reports) + +static wmOperator *wm_operator_create(wmWindowManager *wm, wmOperatorType *ot, PointerRNA *properties, ReportList *reports) +{ + wmOperator *op= MEM_callocN(sizeof(wmOperator), ot->idname); /* XXX operatortype names are static still. for debug */ + + /* XXX adding new operator could be function, only happens here now */ + op->type= ot; + BLI_strncpy(op->idname, ot->idname, OP_MAX_TYPENAME); + + /* initialize properties, either copy or create */ + op->ptr= MEM_callocN(sizeof(PointerRNA), "wmOperatorPtrRNA"); + if(properties && properties->data) { + op->properties= IDP_CopyProperty(properties->data); + } + else { + IDPropertyTemplate val = {0}; + op->properties= IDP_New(IDP_GROUP, val, "wmOperatorProperties"); + } + RNA_pointer_create(&wm->id, ot->srna, op->properties, op->ptr); + + /* initialize error reports */ + if (reports) { + op->reports= reports; /* must be initialized alredy */ + } + else { + op->reports= MEM_mallocN(sizeof(ReportList), "wmOperatorReportList"); + BKE_reports_init(op->reports, RPT_STORE); + } + + return op; +} + +static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, PointerRNA *properties) { wmWindowManager *wm= CTX_wm_manager(C); int retval= OPERATOR_PASS_THROUGH; if(ot->poll==NULL || ot->poll(C)) { - wmOperator *op= MEM_callocN(sizeof(wmOperator), ot->idname); /* XXX operatortype names are static still. for debug */ - + wmOperator *op= wm_operator_create(wm, ot, properties, NULL); + if((G.f & G_DEBUG) && event && event->type!=MOUSEMOVE) printf("handle evt %d win %d op %s\n", event?event->type:0, CTX_wm_screen(C)->subwinactive, ot->idname); - /* XXX adding new operator could be function, only happens here now */ - op->type= ot; - BLI_strncpy(op->idname, ot->idname, OP_MAX_TYPENAME); - - /* initialize properties, either copy or create */ - op->ptr= MEM_callocN(sizeof(PointerRNA), "wmOperatorPtrRNA"); - if(properties && properties->data) { - op->properties= IDP_CopyProperty(properties->data); - } - else { - IDPropertyTemplate val = {0}; - op->properties= IDP_New(IDP_GROUP, val, "wmOperatorProperties"); - } - RNA_pointer_create(&wm->id, ot->srna, op->properties, op->ptr); - - /* initialize error reports */ - if (reports) { - op->reports= reports; /* must be initialized alredy */ - } - else { - op->reports= MEM_mallocN(sizeof(ReportList), "wmOperatorReportList"); - BKE_reports_init(op->reports, RPT_STORE); - } - if(op->type->invoke && event) retval= (*op->type->invoke)(C, op, event); else if(op->type->exec) @@ -483,7 +491,7 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, P printf("invalid operator call %s\n", ot->idname); /* debug, important to leave a while, should never happen */ if(!(retval & OPERATOR_RUNNING_MODAL)) { - if(reports==NULL && op->reports->list.first) /* only show the report if the report list was not given in the function */ + if(op->reports->list.first) /* only show the report if the report list was not given in the function */ uiPupmenuReports(C, op->reports); if (retval & OPERATOR_FINISHED) /* todo - this may conflict with the other WM_operator_print, if theres ever 2 prints for 1 action will may need to add modal check here */ @@ -495,8 +503,6 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, P wm_operator_register(wm, op); } else if(!(retval & OPERATOR_RUNNING_MODAL)) { - if (reports) - op->reports= NULL; /* dont let the operator free reports passed to this function */ WM_operator_free(op); } } @@ -505,7 +511,7 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, P } /* invokes operator in context */ -int WM_operator_name_call(bContext *C, const char *opstring, int context, PointerRNA *properties, ReportList *reports) +int WM_operator_name_call(bContext *C, const char *opstring, int context, PointerRNA *properties) { wmOperatorType *ot= WM_operatortype_find(opstring); wmWindow *window= CTX_wm_window(C); @@ -535,7 +541,7 @@ int WM_operator_name_call(bContext *C, const char *opstring, int context, Pointe CTX_wm_region_set(C, ar1); } - retval= wm_operator_invoke(C, ot, event, properties, reports); + retval= wm_operator_invoke(C, ot, event, properties); /* set region back */ CTX_wm_region_set(C, ar); @@ -550,7 +556,7 @@ int WM_operator_name_call(bContext *C, const char *opstring, int context, Pointe ARegion *ar= CTX_wm_region(C); CTX_wm_region_set(C, NULL); - retval= wm_operator_invoke(C, ot, event, properties, reports); + retval= wm_operator_invoke(C, ot, event, properties); CTX_wm_region_set(C, ar); return retval; @@ -565,7 +571,7 @@ int WM_operator_name_call(bContext *C, const char *opstring, int context, Pointe CTX_wm_region_set(C, NULL); CTX_wm_area_set(C, NULL); - retval= wm_operator_invoke(C, ot, window->eventstate, properties, reports); + retval= wm_operator_invoke(C, ot, window->eventstate, properties); CTX_wm_region_set(C, ar); CTX_wm_area_set(C, area); @@ -574,13 +580,32 @@ int WM_operator_name_call(bContext *C, const char *opstring, int context, Pointe case WM_OP_EXEC_DEFAULT: event= NULL; /* pass on without break */ case WM_OP_INVOKE_DEFAULT: - return wm_operator_invoke(C, ot, event, properties, reports); + return wm_operator_invoke(C, ot, event, properties); } } return 0; } +/* Similar to WM_operator_name_call called with WM_OP_EXEC_DEFAULT context. + - wmOperatorType is used instead of operator name since python alredy has the operator type + - poll() must be called by python before this runs. + - reports can be passed to this function (so python can report them as exceptions) +*/ +int WM_operator_call_py(bContext *C, wmOperatorType *ot, PointerRNA *properties, ReportList *reports) +{ + wmWindowManager *wm= CTX_wm_manager(C); + wmOperator *op= wm_operator_create(wm, ot, properties, reports); + int retval= op->type->exec(C, op); + + if (reports) + op->reports= NULL; /* dont let the operator free reports passed to this function */ + WM_operator_free(op); + + return retval; +} + + /* ********************* handlers *************** */ /* not handler itself, is called by UI to move handlers to other queues, so don't close modal ones */ @@ -773,7 +798,7 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand wmOperatorType *ot= WM_operatortype_find(event->keymap_idname); if(ot) - retval= wm_operator_invoke(C, ot, event, properties, NULL); + retval= wm_operator_invoke(C, ot, event, properties); } if(retval & OPERATOR_PASS_THROUGH)