diff options
Diffstat (limited to 'source/blender/windowmanager/intern/wm_operators.c')
-rw-r--r-- | source/blender/windowmanager/intern/wm_operators.c | 416 |
1 files changed, 1 insertions, 415 deletions
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index b81790abaad..d2fb49ffd57 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -119,395 +119,9 @@ #include "wm_files.h" #include "wm_window.h" -static GHash *global_ops_hash = NULL; - #define UNDOCUMENTED_OPERATOR_TIP N_("(undocumented operator)") /* ************ operator API, exported ********** */ - - -wmOperatorType *WM_operatortype_find(const char *idname, bool quiet) -{ - if (idname[0]) { - wmOperatorType *ot; - - /* needed to support python style names without the _OT_ syntax */ - char idname_bl[OP_MAX_TYPENAME]; - WM_operator_bl_idname(idname_bl, idname); - - ot = BLI_ghash_lookup(global_ops_hash, idname_bl); - if (ot) { - return ot; - } - - if (!quiet) { - CLOG_INFO(WM_LOG_OPERATORS, 0, "search for unknown operator '%s', '%s'\n", idname_bl, idname); - } - } - else { - if (!quiet) { - CLOG_INFO(WM_LOG_OPERATORS, 0, "search for empty operator"); - } - } - - return NULL; -} - -/* caller must free */ -void WM_operatortype_iter(GHashIterator *ghi) -{ - BLI_ghashIterator_init(ghi, global_ops_hash); -} - -/* all ops in 1 list (for time being... needs evaluation later) */ -void WM_operatortype_append(void (*opfunc)(wmOperatorType *)) -{ - wmOperatorType *ot; - - ot = MEM_callocN(sizeof(wmOperatorType), "operatortype"); - ot->srna = RNA_def_struct_ptr(&BLENDER_RNA, "", &RNA_OperatorProperties); - /* Set the default i18n context now, so that opfunc can redefine it if needed! */ - RNA_def_struct_translation_context(ot->srna, BLT_I18NCONTEXT_OPERATOR_DEFAULT); - ot->translation_context = BLT_I18NCONTEXT_OPERATOR_DEFAULT; - opfunc(ot); - - if (ot->name == NULL) { - CLOG_ERROR(WM_LOG_OPERATORS, "Operator '%s' has no name property", ot->idname); - } - - /* XXX All ops should have a description but for now allow them not to. */ - RNA_def_struct_ui_text(ot->srna, ot->name, ot->description ? ot->description : UNDOCUMENTED_OPERATOR_TIP); - RNA_def_struct_identifier(&BLENDER_RNA, ot->srna, ot->idname); - - BLI_ghash_insert(global_ops_hash, (void *)ot->idname, ot); -} - -void WM_operatortype_append_ptr(void (*opfunc)(wmOperatorType *, void *), void *userdata) -{ - wmOperatorType *ot; - - ot = MEM_callocN(sizeof(wmOperatorType), "operatortype"); - ot->srna = RNA_def_struct_ptr(&BLENDER_RNA, "", &RNA_OperatorProperties); - /* Set the default i18n context now, so that opfunc can redefine it if needed! */ - RNA_def_struct_translation_context(ot->srna, BLT_I18NCONTEXT_OPERATOR_DEFAULT); - ot->translation_context = BLT_I18NCONTEXT_OPERATOR_DEFAULT; - opfunc(ot, userdata); - RNA_def_struct_ui_text(ot->srna, ot->name, ot->description ? ot->description : UNDOCUMENTED_OPERATOR_TIP); - RNA_def_struct_identifier(&BLENDER_RNA, ot->srna, ot->idname); - - BLI_ghash_insert(global_ops_hash, (void *)ot->idname, ot); -} - -/* ********************* macro operator ******************** */ - -typedef struct { - int retval; -} MacroData; - -static void wm_macro_start(wmOperator *op) -{ - if (op->customdata == NULL) { - op->customdata = MEM_callocN(sizeof(MacroData), "MacroData"); - } -} - -static int wm_macro_end(wmOperator *op, int retval) -{ - if (retval & OPERATOR_CANCELLED) { - MacroData *md = op->customdata; - - if (md->retval & OPERATOR_FINISHED) { - retval |= OPERATOR_FINISHED; - retval &= ~OPERATOR_CANCELLED; - } - } - - /* if modal is ending, free custom data */ - if (retval & (OPERATOR_FINISHED | OPERATOR_CANCELLED)) { - if (op->customdata) { - MEM_freeN(op->customdata); - op->customdata = NULL; - } - } - - return retval; -} - -/* macro exec only runs exec calls */ -static int wm_macro_exec(bContext *C, wmOperator *op) -{ - wmOperator *opm; - int retval = OPERATOR_FINISHED; - - wm_macro_start(op); - - for (opm = op->macro.first; opm; opm = opm->next) { - - if (opm->type->exec) { - retval = opm->type->exec(C, opm); - OPERATOR_RETVAL_CHECK(retval); - - if (retval & OPERATOR_FINISHED) { - MacroData *md = op->customdata; - md->retval = OPERATOR_FINISHED; /* keep in mind that at least one operator finished */ - } - else { - break; /* operator didn't finish, end macro */ - } - } - else { - CLOG_WARN(WM_LOG_OPERATORS, "'%s' cant exec macro", opm->type->idname); - } - } - - return wm_macro_end(op, retval); -} - -static int wm_macro_invoke_internal(bContext *C, wmOperator *op, const wmEvent *event, wmOperator *opm) -{ - int retval = OPERATOR_FINISHED; - - /* start from operator received as argument */ - for (; opm; opm = opm->next) { - if (opm->type->invoke) - retval = opm->type->invoke(C, opm, event); - else if (opm->type->exec) - retval = opm->type->exec(C, opm); - - OPERATOR_RETVAL_CHECK(retval); - - BLI_movelisttolist(&op->reports->list, &opm->reports->list); - - if (retval & OPERATOR_FINISHED) { - MacroData *md = op->customdata; - md->retval = OPERATOR_FINISHED; /* keep in mind that at least one operator finished */ - } - else { - break; /* operator didn't finish, end macro */ - } - } - - return wm_macro_end(op, retval); -} - -static int wm_macro_invoke(bContext *C, wmOperator *op, const wmEvent *event) -{ - wm_macro_start(op); - return wm_macro_invoke_internal(C, op, event, op->macro.first); -} - -static int wm_macro_modal(bContext *C, wmOperator *op, const wmEvent *event) -{ - wmOperator *opm = op->opm; - int retval = OPERATOR_FINISHED; - - if (opm == NULL) { - CLOG_ERROR(WM_LOG_OPERATORS, "macro error, calling NULL modal()"); - } - else { - retval = opm->type->modal(C, opm, event); - OPERATOR_RETVAL_CHECK(retval); - - /* if we're halfway through using a tool and cancel it, clear the options [#37149] */ - if (retval & OPERATOR_CANCELLED) { - WM_operator_properties_clear(opm->ptr); - } - - /* if this one is done but it's not the last operator in the macro */ - if ((retval & OPERATOR_FINISHED) && opm->next) { - MacroData *md = op->customdata; - - md->retval = OPERATOR_FINISHED; /* keep in mind that at least one operator finished */ - - retval = wm_macro_invoke_internal(C, op, event, opm->next); - - /* if new operator is modal and also added its own handler */ - if (retval & OPERATOR_RUNNING_MODAL && op->opm != opm) { - wmWindow *win = CTX_wm_window(C); - wmEventHandler *handler; - - handler = BLI_findptr(&win->modalhandlers, op, offsetof(wmEventHandler, op)); - if (handler) { - BLI_remlink(&win->modalhandlers, handler); - wm_event_free_handler(handler); - } - - /* if operator is blocking, grab cursor - * This may end up grabbing twice, but we don't care. - * */ - if (op->opm->type->flag & OPTYPE_BLOCKING) { - int bounds[4] = {-1, -1, -1, -1}; - const bool wrap = ( - (U.uiflag & USER_CONTINUOUS_MOUSE) && - ((op->opm->flag & OP_IS_MODAL_GRAB_CURSOR) || (op->opm->type->flag & OPTYPE_GRAB_CURSOR))); - - if (wrap) { - ARegion *ar = CTX_wm_region(C); - if (ar) { - bounds[0] = ar->winrct.xmin; - bounds[1] = ar->winrct.ymax; - bounds[2] = ar->winrct.xmax; - bounds[3] = ar->winrct.ymin; - } - } - - WM_cursor_grab_enable(win, wrap, false, bounds); - } - } - } - } - - return wm_macro_end(op, retval); -} - -static void wm_macro_cancel(bContext *C, wmOperator *op) -{ - /* call cancel on the current modal operator, if any */ - if (op->opm && op->opm->type->cancel) { - op->opm->type->cancel(C, op->opm); - } - - wm_macro_end(op, OPERATOR_CANCELLED); -} - -/* Names have to be static for now */ -wmOperatorType *WM_operatortype_append_macro(const char *idname, const char *name, const char *description, int flag) -{ - wmOperatorType *ot; - const char *i18n_context; - - if (WM_operatortype_find(idname, true)) { - CLOG_ERROR(WM_LOG_OPERATORS, "operator %s exists, cannot create macro", idname); - return NULL; - } - - ot = MEM_callocN(sizeof(wmOperatorType), "operatortype"); - ot->srna = RNA_def_struct_ptr(&BLENDER_RNA, "", &RNA_OperatorProperties); - - ot->idname = idname; - ot->name = name; - ot->description = description; - ot->flag = OPTYPE_MACRO | flag; - - ot->exec = wm_macro_exec; - ot->invoke = wm_macro_invoke; - ot->modal = wm_macro_modal; - ot->cancel = wm_macro_cancel; - ot->poll = NULL; - - if (!ot->description) /* XXX All ops should have a description but for now allow them not to. */ - ot->description = UNDOCUMENTED_OPERATOR_TIP; - - RNA_def_struct_ui_text(ot->srna, ot->name, ot->description); - RNA_def_struct_identifier(&BLENDER_RNA, ot->srna, ot->idname); - /* Use i18n context from ext.srna if possible (py operators). */ - i18n_context = ot->ext.srna ? RNA_struct_translation_context(ot->ext.srna) : BLT_I18NCONTEXT_OPERATOR_DEFAULT; - RNA_def_struct_translation_context(ot->srna, i18n_context); - ot->translation_context = i18n_context; - - BLI_ghash_insert(global_ops_hash, (void *)ot->idname, ot); - - return ot; -} - -void WM_operatortype_append_macro_ptr(void (*opfunc)(wmOperatorType *, void *), void *userdata) -{ - wmOperatorType *ot; - - ot = MEM_callocN(sizeof(wmOperatorType), "operatortype"); - ot->srna = RNA_def_struct_ptr(&BLENDER_RNA, "", &RNA_OperatorProperties); - - ot->flag = OPTYPE_MACRO; - ot->exec = wm_macro_exec; - ot->invoke = wm_macro_invoke; - ot->modal = wm_macro_modal; - ot->cancel = wm_macro_cancel; - ot->poll = NULL; - - if (!ot->description) - ot->description = UNDOCUMENTED_OPERATOR_TIP; - - /* Set the default i18n context now, so that opfunc can redefine it if needed! */ - RNA_def_struct_translation_context(ot->srna, BLT_I18NCONTEXT_OPERATOR_DEFAULT); - ot->translation_context = BLT_I18NCONTEXT_OPERATOR_DEFAULT; - opfunc(ot, userdata); - - RNA_def_struct_ui_text(ot->srna, ot->name, ot->description); - RNA_def_struct_identifier(&BLENDER_RNA, ot->srna, ot->idname); - - BLI_ghash_insert(global_ops_hash, (void *)ot->idname, ot); -} - -wmOperatorTypeMacro *WM_operatortype_macro_define(wmOperatorType *ot, const char *idname) -{ - wmOperatorTypeMacro *otmacro = MEM_callocN(sizeof(wmOperatorTypeMacro), "wmOperatorTypeMacro"); - - BLI_strncpy(otmacro->idname, idname, OP_MAX_TYPENAME); - - /* do this on first use, since operatordefinitions might have been not done yet */ - WM_operator_properties_alloc(&(otmacro->ptr), &(otmacro->properties), idname); - WM_operator_properties_sanitize(otmacro->ptr, 1); - - BLI_addtail(&ot->macro, otmacro); - - { - /* operator should always be found but in the event its not. don't segfault */ - wmOperatorType *otsub = WM_operatortype_find(idname, 0); - if (otsub) { - RNA_def_pointer_runtime(ot->srna, otsub->idname, otsub->srna, - otsub->name, otsub->description); - } - } - - return otmacro; -} - -static void wm_operatortype_free_macro(wmOperatorType *ot) -{ - wmOperatorTypeMacro *otmacro; - - for (otmacro = ot->macro.first; otmacro; otmacro = otmacro->next) { - if (otmacro->ptr) { - WM_operator_properties_free(otmacro->ptr); - MEM_freeN(otmacro->ptr); - } - } - BLI_freelistN(&ot->macro); -} - -void WM_operatortype_remove_ptr(wmOperatorType *ot) -{ - BLI_assert(ot == WM_operatortype_find(ot->idname, false)); - - RNA_struct_free(&BLENDER_RNA, ot->srna); - - if (ot->last_properties) { - IDP_FreeProperty(ot->last_properties); - MEM_freeN(ot->last_properties); - } - - if (ot->macro.first) - wm_operatortype_free_macro(ot); - - BLI_ghash_remove(global_ops_hash, ot->idname, NULL, NULL); - - WM_keyconfig_update_operatortype(); - - MEM_freeN(ot); -} - -bool WM_operatortype_remove(const char *idname) -{ - wmOperatorType *ot = WM_operatortype_find(idname, 0); - - if (ot == NULL) - return false; - - WM_operatortype_remove_ptr(ot); - - return true; -} - /** * Remove memory of all previously executed tools. */ @@ -3457,22 +3071,6 @@ static void WM_OT_doc_view_manual_ui_context(wmOperatorType *ot) /* ******************************************************* */ -static void operatortype_ghash_free_cb(wmOperatorType *ot) -{ - if (ot->last_properties) { - IDP_FreeProperty(ot->last_properties); - MEM_freeN(ot->last_properties); - } - - if (ot->macro.first) - wm_operatortype_free_macro(ot); - - if (ot->ext.srna) /* python operator, allocs own string */ - MEM_freeN((void *)ot->idname); - - MEM_freeN(ot); -} - /* ******************************************************* */ /* toggle 3D for current window, turning it fullscreen if needed */ static void WM_OT_stereo3d_set(wmOperatorType *ot) @@ -3504,20 +3102,8 @@ static void WM_OT_stereo3d_set(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } -/* ******************************************************* */ -/* called on initialize WM_exit() */ -void wm_operatortype_free(void) +void wm_operatortypes_register(void) { - BLI_ghash_free(global_ops_hash, NULL, (GHashValFreeFP)operatortype_ghash_free_cb); - global_ops_hash = NULL; -} - -/* called on initialize WM_init() */ -void wm_operatortype_init(void) -{ - /* reserve size is set based on blender default setup */ - global_ops_hash = BLI_ghash_str_new_ex("wm_operatortype_init gh", 2048); - WM_operatortype_append(WM_OT_window_close); WM_operatortype_append(WM_OT_window_duplicate); WM_operatortype_append(WM_OT_read_history); |