Merge branch 'master' into blender2.8
This commit is contained in:
commit
2ead3f0765
|
@ -56,7 +56,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
|
||||
|
@ -68,13 +67,17 @@ 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_subwindow.c
|
||||
intern/wm_window.c
|
||||
intern/wm_playanim.c
|
||||
intern/wm_stereo.c
|
||||
intern/wm_subwindow.c
|
||||
intern/wm_toolsystem.c
|
||||
intern/wm_tooltip.c
|
||||
intern/wm_uilist_type.c
|
||||
intern/wm_window.c
|
||||
manipulators/intern/wm_manipulator.c
|
||||
manipulators/intern/wm_manipulator_group.c
|
||||
manipulators/intern/wm_manipulator_group_type.c
|
||||
|
|
|
@ -207,6 +207,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();
|
||||
wm_manipulatortype_init();
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,546 @@
|
|||
/*
|
||||
* ***** 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 "RNA_enum_types.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;
|
||||
/** Counter for operator-properties that should not be tagged with #OP_PROP_TAG_ADVANCED. */
|
||||
static int ot_prop_basic_count = -1;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/** \name Operator Type Append
|
||||
* \{ */
|
||||
|
||||
static wmOperatorType *wm_operatortype_append__begin(void)
|
||||
{
|
||||
wmOperatorType *ot = MEM_callocN(sizeof(wmOperatorType), "operatortype");
|
||||
|
||||
BLI_assert(ot_prop_basic_count == -1);
|
||||
|
||||
ot->srna = RNA_def_struct_ptr(&BLENDER_RNA, "", &RNA_OperatorProperties);
|
||||
RNA_def_struct_property_tags(ot->srna, rna_enum_operator_property_tags);
|
||||
/* 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;
|
||||
|
||||
return ot;
|
||||
}
|
||||
static void wm_operatortype_append__end(wmOperatorType *ot)
|
||||
{
|
||||
if (ot->name == NULL) {
|
||||
CLOG_ERROR(WM_LOG_OPERATORS, "Operator '%s' has no name property", ot->idname);
|
||||
}
|
||||
|
||||
/* Allow calling _begin without _end in operatortype creation. */
|
||||
WM_operatortype_props_advanced_end(ot);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* all ops in 1 list (for time being... needs evaluation later) */
|
||||
void WM_operatortype_append(void (*opfunc)(wmOperatorType *))
|
||||
{
|
||||
wmOperatorType *ot = wm_operatortype_append__begin();
|
||||
opfunc(ot);
|
||||
wm_operatortype_append__end(ot);
|
||||
}
|
||||
|
||||
void WM_operatortype_append_ptr(void (*opfunc)(wmOperatorType *, void *), void *userdata)
|
||||
{
|
||||
wmOperatorType *ot = wm_operatortype_append__begin();
|
||||
opfunc(ot, userdata);
|
||||
wm_operatortype_append__end(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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tag all operator-properties of \a ot defined after calling this, until
|
||||
* the next #WM_operatortype_props_advanced_end call (if available), with
|
||||
* #OP_PROP_TAG_ADVANCED. Previously defined ones properties not touched.
|
||||
*
|
||||
* Calling this multiple times without a call to #WM_operatortype_props_advanced_end,
|
||||
* all calls after the first one are ignored. Meaning all propereties defined after the
|
||||
* first call are tagged as advanced.
|
||||
*
|
||||
* This doesn't do the actual tagging, #WM_operatortype_props_advanced_end does which is
|
||||
* called for all operators during registration (see #wm_operatortype_append__end).
|
||||
*/
|
||||
void WM_operatortype_props_advanced_begin(wmOperatorType *ot)
|
||||
{
|
||||
if (ot_prop_basic_count == -1) { /* Don't do anything if _begin was called before, but not _end */
|
||||
ot_prop_basic_count = RNA_struct_count_properties(ot->srna);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tags all operator-properties of \ot defined since the first #WM_operatortype_props_advanced_begin
|
||||
* call, or the last #WM_operatortype_props_advanced_end call, with #OP_PROP_TAG_ADVANCED.
|
||||
* Note that this is called for all operators during registration (see #wm_operatortype_append__end).
|
||||
* So it does not need to be explicitly called in operator-type definition.
|
||||
*/
|
||||
void WM_operatortype_props_advanced_end(wmOperatorType *ot)
|
||||
{
|
||||
PointerRNA struct_ptr;
|
||||
int counter = 0;
|
||||
|
||||
if (ot_prop_basic_count == -1) {
|
||||
/* WM_operatortype_props_advanced_begin was not called. Don't do anything. */
|
||||
return;
|
||||
}
|
||||
|
||||
RNA_pointer_create(NULL, ot->srna, NULL, &struct_ptr);
|
||||
|
||||
RNA_STRUCT_BEGIN (&struct_ptr, prop)
|
||||
{
|
||||
counter++;
|
||||
if (counter > ot_prop_basic_count) {
|
||||
WM_operatortype_prop_tag(prop, OP_PROP_TAG_ADVANCED);
|
||||
}
|
||||
}
|
||||
RNA_STRUCT_END;
|
||||
|
||||
ot_prop_basic_count = -1;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \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);
|
||||
}
|
||||
|
||||
/** \} */
|
|
@ -120,408 +120,9 @@
|
|||
#include "wm_files.h"
|
||||
#include "wm_window.h"
|
||||
|
||||
static GHash *global_ops_hash = NULL;
|
||||
/** Counter for operator-properties that should not be tagged with #OP_PROP_TAG_ADVANCED. */
|
||||
static int ot_prop_basic_count = -1;
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
/** \name Operator Type Append
|
||||
* \{ */
|
||||
|
||||
static wmOperatorType *wm_operatortype_append__begin(void)
|
||||
{
|
||||
wmOperatorType *ot = MEM_callocN(sizeof(wmOperatorType), "operatortype");
|
||||
|
||||
BLI_assert(ot_prop_basic_count == -1);
|
||||
|
||||
ot->srna = RNA_def_struct_ptr(&BLENDER_RNA, "", &RNA_OperatorProperties);
|
||||
RNA_def_struct_property_tags(ot->srna, rna_enum_operator_property_tags);
|
||||
/* 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;
|
||||
|
||||
return ot;
|
||||
}
|
||||
static void wm_operatortype_append__end(wmOperatorType *ot)
|
||||
{
|
||||
if (ot->name == NULL) {
|
||||
CLOG_ERROR(WM_LOG_OPERATORS, "Operator '%s' has no name property", ot->idname);
|
||||
}
|
||||
|
||||
/* Allow calling _begin without _end in operatortype creation. */
|
||||
WM_operatortype_props_advanced_end(ot);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* all ops in 1 list (for time being... needs evaluation later) */
|
||||
void WM_operatortype_append(void (*opfunc)(wmOperatorType *))
|
||||
{
|
||||
wmOperatorType *ot = wm_operatortype_append__begin();
|
||||
opfunc(ot);
|
||||
wm_operatortype_append__end(ot);
|
||||
}
|
||||
|
||||
void WM_operatortype_append_ptr(void (*opfunc)(wmOperatorType *, void *), void *userdata)
|
||||
{
|
||||
wmOperatorType *ot = wm_operatortype_append__begin();
|
||||
opfunc(ot, userdata);
|
||||
wm_operatortype_append__end(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.
|
||||
*/
|
||||
|
@ -543,55 +144,6 @@ void WM_operatortype_last_properties_clear_all(void)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tag all operator-properties of \a ot defined after calling this, until
|
||||
* the next #WM_operatortype_props_advanced_end call (if available), with
|
||||
* #OP_PROP_TAG_ADVANCED. Previously defined ones properties not touched.
|
||||
*
|
||||
* Calling this multiple times without a call to #WM_operatortype_props_advanced_end,
|
||||
* all calls after the first one are ignored. Meaning all propereties defined after the
|
||||
* first call are tagged as advanced.
|
||||
*
|
||||
* This doesn't do the actual tagging, #WM_operatortype_props_advanced_end does which is
|
||||
* called for all operators during registration (see #wm_operatortype_append__end).
|
||||
*/
|
||||
void WM_operatortype_props_advanced_begin(wmOperatorType *ot)
|
||||
{
|
||||
if (ot_prop_basic_count == -1) { /* Don't do anything if _begin was called before, but not _end */
|
||||
ot_prop_basic_count = RNA_struct_count_properties(ot->srna);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tags all operator-properties of \ot defined since the first #WM_operatortype_props_advanced_begin
|
||||
* call, or the last #WM_operatortype_props_advanced_end call, with #OP_PROP_TAG_ADVANCED.
|
||||
* Note that this is called for all operators during registration (see #wm_operatortype_append__end).
|
||||
* So it does not need to be explicitly called in operator-type definition.
|
||||
*/
|
||||
void WM_operatortype_props_advanced_end(wmOperatorType *ot)
|
||||
{
|
||||
PointerRNA struct_ptr;
|
||||
int counter = 0;
|
||||
|
||||
if (ot_prop_basic_count == -1) {
|
||||
/* WM_operatortype_props_advanced_begin was not called. Don't do anything. */
|
||||
return;
|
||||
}
|
||||
|
||||
RNA_pointer_create(NULL, ot->srna, NULL, &struct_ptr);
|
||||
|
||||
RNA_STRUCT_BEGIN (&struct_ptr, prop)
|
||||
{
|
||||
counter++;
|
||||
if (counter > ot_prop_basic_count) {
|
||||
WM_operatortype_prop_tag(prop, OP_PROP_TAG_ADVANCED);
|
||||
}
|
||||
}
|
||||
RNA_STRUCT_END;
|
||||
|
||||
ot_prop_basic_count = -1;
|
||||
}
|
||||
|
||||
/* SOME_OT_op -> some.op */
|
||||
void WM_operator_py_idname(char *to, const char *from)
|
||||
{
|
||||
|
@ -3648,24 +3200,6 @@ static void WM_OT_doc_view_manual_ui_context(wmOperatorType *ot)
|
|||
ot->exec = doc_view_manual_ui_context_exec;
|
||||
}
|
||||
|
||||
/* ******************************************************* */
|
||||
|
||||
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)
|
||||
|
@ -3697,20 +3231,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_new);
|
||||
WM_operatortype_append(WM_OT_window_new_main);
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -62,6 +62,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);
|
||||
|
|
Loading…
Reference in New Issue