Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2018-07-13 13:15:18 +0300
committerCampbell Barton <ideasman42@gmail.com>2018-07-13 13:20:42 +0300
commit8ff3f7f6013f730f5325dbcbbfcb4e78fae19bbb (patch)
tree1b86f81c4043224945be22efac67e277006b05d0
parent30bffb5a3afa2fde165d4fb63a115310d5ddc3e3 (diff)
Cleanup: move WM type registration into own files
Type registration is mostly boiler plate logic, which can be separated from other API's.
-rw-r--r--source/blender/windowmanager/CMakeLists.txt7
-rw-r--r--source/blender/windowmanager/intern/wm.c124
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c2
-rw-r--r--source/blender/windowmanager/intern/wm_menu_type.c105
-rw-r--r--source/blender/windowmanager/intern/wm_operator_type.c483
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c416
-rw-r--r--source/blender/windowmanager/intern/wm_uilist_type.c98
-rw-r--r--source/blender/windowmanager/wm.h1
8 files changed, 695 insertions, 541 deletions
diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt
index 50f99251489..810cceb5fc3 100644
--- a/source/blender/windowmanager/CMakeLists.txt
+++ b/source/blender/windowmanager/CMakeLists.txt
@@ -53,7 +53,6 @@ set(INC_SYS
set(SRC
intern/wm.c
- intern/wm_playanim.c
intern/wm_cursors.c
intern/wm_dragdrop.c
intern/wm_draw.c
@@ -65,12 +64,16 @@ set(SRC
intern/wm_init_exit.c
intern/wm_jobs.c
intern/wm_keymap.c
+ intern/wm_menu_type.c
intern/wm_operator_props.c
+ intern/wm_operator_type.c
intern/wm_operators.c
+ intern/wm_playanim.c
+ intern/wm_stereo.c
intern/wm_subwindow.c
intern/wm_tooltip.c
+ intern/wm_uilist_type.c
intern/wm_window.c
- intern/wm_stereo.c
WM_api.h
WM_keymap.h
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index b3b8bf5734d..132789aade4 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -222,130 +222,6 @@ void WM_operator_handlers_clear(wmWindowManager *wm, wmOperatorType *ot)
}
/* ************ uiListType handling ************** */
-
-static GHash *uilisttypes_hash = NULL;
-
-uiListType *WM_uilisttype_find(const char *idname, bool quiet)
-{
- uiListType *ult;
-
- if (idname[0]) {
- ult = BLI_ghash_lookup(uilisttypes_hash, idname);
- if (ult) {
- return ult;
- }
- }
-
- if (!quiet) {
- printf("search for unknown uilisttype %s\n", idname);
- }
-
- return NULL;
-}
-
-bool WM_uilisttype_add(uiListType *ult)
-{
- BLI_ghash_insert(uilisttypes_hash, ult->idname, ult);
- return 1;
-}
-
-void WM_uilisttype_freelink(uiListType *ult)
-{
- bool ok;
-
- ok = BLI_ghash_remove(uilisttypes_hash, ult->idname, NULL, MEM_freeN);
-
- BLI_assert(ok);
- (void)ok;
-}
-
-/* called on initialize WM_init() */
-void WM_uilisttype_init(void)
-{
- uilisttypes_hash = BLI_ghash_str_new_ex("uilisttypes_hash gh", 16);
-}
-
-void WM_uilisttype_free(void)
-{
- GHashIterator gh_iter;
-
- GHASH_ITER (gh_iter, uilisttypes_hash) {
- uiListType *ult = BLI_ghashIterator_getValue(&gh_iter);
- if (ult->ext.free) {
- ult->ext.free(ult->ext.data);
- }
- }
-
- BLI_ghash_free(uilisttypes_hash, NULL, MEM_freeN);
- uilisttypes_hash = NULL;
-}
-
-/* ************ MenuType handling ************** */
-
-static GHash *menutypes_hash = NULL;
-
-MenuType *WM_menutype_find(const char *idname, bool quiet)
-{
- MenuType *mt;
-
- if (idname[0]) {
- mt = BLI_ghash_lookup(menutypes_hash, idname);
- if (mt)
- return mt;
- }
-
- if (!quiet)
- printf("search for unknown menutype %s\n", idname);
-
- return NULL;
-}
-
-bool WM_menutype_add(MenuType *mt)
-{
- BLI_ghash_insert(menutypes_hash, mt->idname, mt);
- return true;
-}
-
-void WM_menutype_freelink(MenuType *mt)
-{
- bool ok;
-
- ok = BLI_ghash_remove(menutypes_hash, mt->idname, NULL, MEM_freeN);
-
- BLI_assert(ok);
- (void)ok;
-}
-
-/* called on initialize WM_init() */
-void WM_menutype_init(void)
-{
- /* reserve size is set based on blender default setup */
- menutypes_hash = BLI_ghash_str_new_ex("menutypes_hash gh", 512);
-}
-
-void WM_menutype_free(void)
-{
- GHashIterator gh_iter;
-
- GHASH_ITER (gh_iter, menutypes_hash) {
- MenuType *mt = BLI_ghashIterator_getValue(&gh_iter);
- if (mt->ext.free) {
- mt->ext.free(mt->ext.data);
- }
- }
-
- BLI_ghash_free(menutypes_hash, NULL, MEM_freeN);
- menutypes_hash = NULL;
-}
-
-bool WM_menutype_poll(bContext *C, MenuType *mt)
-{
- if (mt->poll != NULL) {
- return mt->poll(C, mt);
- }
- return true;
-}
-
/* ****************************************** */
void WM_keymap_init(bContext *C)
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 449a0a91a01..088327fa611 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -166,6 +166,8 @@ void WM_init(bContext *C, int argc, const char **argv)
BKE_addon_pref_type_init();
wm_operatortype_init();
+ wm_operatortypes_register();
+
WM_menutype_init();
WM_uilisttype_init();
diff --git a/source/blender/windowmanager/intern/wm_menu_type.c b/source/blender/windowmanager/intern/wm_menu_type.c
new file mode 100644
index 00000000000..58e85716bf1
--- /dev/null
+++ b/source/blender/windowmanager/intern/wm_menu_type.c
@@ -0,0 +1,105 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/windowmanager/intern/wm_menu_type.c
+ * \ingroup wm
+ *
+ * Menu Registry.
+ */
+
+#include "BLI_sys_types.h"
+
+#include "DNA_windowmanager_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+
+#include "BKE_context.h"
+#include "BKE_library.h"
+#include "BKE_screen.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+static GHash *menutypes_hash = NULL;
+
+MenuType *WM_menutype_find(const char *idname, bool quiet)
+{
+ MenuType *mt;
+
+ if (idname[0]) {
+ mt = BLI_ghash_lookup(menutypes_hash, idname);
+ if (mt)
+ return mt;
+ }
+
+ if (!quiet)
+ printf("search for unknown menutype %s\n", idname);
+
+ return NULL;
+}
+
+bool WM_menutype_add(MenuType *mt)
+{
+ BLI_ghash_insert(menutypes_hash, mt->idname, mt);
+ return true;
+}
+
+void WM_menutype_freelink(MenuType *mt)
+{
+ bool ok;
+
+ ok = BLI_ghash_remove(menutypes_hash, mt->idname, NULL, MEM_freeN);
+
+ BLI_assert(ok);
+ (void)ok;
+}
+
+/* called on initialize WM_init() */
+void WM_menutype_init(void)
+{
+ /* reserve size is set based on blender default setup */
+ menutypes_hash = BLI_ghash_str_new_ex("menutypes_hash gh", 512);
+}
+
+void WM_menutype_free(void)
+{
+ GHashIterator gh_iter;
+
+ GHASH_ITER (gh_iter, menutypes_hash) {
+ MenuType *mt = BLI_ghashIterator_getValue(&gh_iter);
+ if (mt->ext.free) {
+ mt->ext.free(mt->ext.data);
+ }
+ }
+
+ BLI_ghash_free(menutypes_hash, NULL, MEM_freeN);
+ menutypes_hash = NULL;
+}
+
+bool WM_menutype_poll(bContext *C, MenuType *mt)
+{
+ if (mt->poll != NULL) {
+ return mt->poll(C, mt);
+ }
+ return true;
+}
diff --git a/source/blender/windowmanager/intern/wm_operator_type.c b/source/blender/windowmanager/intern/wm_operator_type.c
new file mode 100644
index 00000000000..35efdb2c4a2
--- /dev/null
+++ b/source/blender/windowmanager/intern/wm_operator_type.c
@@ -0,0 +1,483 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/windowmanager/intern/wm_operator_type.c
+ * \ingroup wm
+ *
+ * Operator Registry.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "CLG_log.h"
+
+#include "DNA_ID.h"
+#include "DNA_screen_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BLT_translation.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+
+#include "BKE_context.h"
+#include "BKE_idprop.h"
+#include "BKE_library.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "wm.h"
+#include "wm_event_system.h"
+
+#define UNDOCUMENTED_OPERATOR_TIP N_("(undocumented operator)")
+
+static void wm_operatortype_free_macro(wmOperatorType *ot);
+
+/* -------------------------------------------------------------------- */
+/** \name Operator Type Registry
+ * \{ */
+
+static GHash *global_ops_hash = NULL;
+
+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);
+}
+
+
+/* called on initialize WM_exit() */
+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;
+}
+
+/* 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);
+}
+
+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);
+}
+
+void wm_operatortype_free(void)
+{
+ BLI_ghash_free(global_ops_hash, NULL, (GHashValFreeFP)operatortype_ghash_free_cb);
+ global_ops_hash = NULL;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Operator Macro Type
+ * \{ */
+
+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);
+}
+
+/** \} */
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);
diff --git a/source/blender/windowmanager/intern/wm_uilist_type.c b/source/blender/windowmanager/intern/wm_uilist_type.c
new file mode 100644
index 00000000000..52619a09218
--- /dev/null
+++ b/source/blender/windowmanager/intern/wm_uilist_type.c
@@ -0,0 +1,98 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/windowmanager/intern/wm_uilist_type.c
+ * \ingroup wm
+ *
+ * UI List Registry.
+ */
+
+#include "BLI_sys_types.h"
+
+#include "DNA_windowmanager_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+
+#include "BKE_context.h"
+#include "BKE_library.h"
+#include "BKE_screen.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+static GHash *uilisttypes_hash = NULL;
+
+uiListType *WM_uilisttype_find(const char *idname, bool quiet)
+{
+ uiListType *ult;
+
+ if (idname[0]) {
+ ult = BLI_ghash_lookup(uilisttypes_hash, idname);
+ if (ult) {
+ return ult;
+ }
+ }
+
+ if (!quiet) {
+ printf("search for unknown uilisttype %s\n", idname);
+ }
+
+ return NULL;
+}
+
+bool WM_uilisttype_add(uiListType *ult)
+{
+ BLI_ghash_insert(uilisttypes_hash, ult->idname, ult);
+ return 1;
+}
+
+void WM_uilisttype_freelink(uiListType *ult)
+{
+ bool ok;
+
+ ok = BLI_ghash_remove(uilisttypes_hash, ult->idname, NULL, MEM_freeN);
+
+ BLI_assert(ok);
+ (void)ok;
+}
+
+/* called on initialize WM_init() */
+void WM_uilisttype_init(void)
+{
+ uilisttypes_hash = BLI_ghash_str_new_ex("uilisttypes_hash gh", 16);
+}
+
+void WM_uilisttype_free(void)
+{
+ GHashIterator gh_iter;
+
+ GHASH_ITER (gh_iter, uilisttypes_hash) {
+ uiListType *ult = BLI_ghashIterator_getValue(&gh_iter);
+ if (ult->ext.free) {
+ ult->ext.free(ult->ext.data);
+ }
+ }
+
+ BLI_ghash_free(uilisttypes_hash, NULL, MEM_freeN);
+ uilisttypes_hash = NULL;
+}
diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h
index c0b0e731f4b..5f850a076f0 100644
--- a/source/blender/windowmanager/wm.h
+++ b/source/blender/windowmanager/wm.h
@@ -59,6 +59,7 @@ void wm_operator_register(bContext *C, wmOperator *op);
void wm_operatortype_free(void);
void wm_operatortype_init(void);
void wm_window_keymap(wmKeyConfig *keyconf);
+void wm_operatortypes_register(void);
/* wm_gesture.c */
void wm_gesture_draw(struct wmWindow *win);