Python operator api was using WM_operator_name_call() which was confusing things too much.
Added WM_operator_call_py() which ended up being a very small function and split out operator creation into wm_operator_create()
Python operator now runs the poll() function and raises an error if it fails.
Eventually there should be error messages for poll that python can use to give the exact reason for failing (eg - library linked data, no active object...)
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);
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)
{
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;
}
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;
}
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;
}
}
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);
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);
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();
// 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;
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);
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);
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);
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) {
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) {
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) {
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);
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);
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);
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)
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 */
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);
}
}
}
/* 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);
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);
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;
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);
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 */
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)