diff options
author | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2013-02-16 22:38:03 +0400 |
---|---|---|
committer | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2013-02-16 22:38:03 +0400 |
commit | 92436c94d3adbbfc285bd7b3041db36e66dae5d5 (patch) | |
tree | 2083c8ad4fa810a781e9631161aa88b12008453d /source/blender/python | |
parent | 90ed5ea4ea278b4aadf9187e4e2b92ef3221001b (diff) | |
parent | fda8927d01ba719963154a56b45952ee541a869d (diff) |
Merged changes in the trunk up to revision 54594.
Diffstat (limited to 'source/blender/python')
-rw-r--r-- | source/blender/python/bmesh/bmesh_py_ops_call.c | 5 | ||||
-rw-r--r-- | source/blender/python/bmesh/bmesh_py_types.c | 54 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_app_translations.c | 107 |
3 files changed, 140 insertions, 26 deletions
diff --git a/source/blender/python/bmesh/bmesh_py_ops_call.c b/source/blender/python/bmesh/bmesh_py_ops_call.c index d4c8033589a..fad3e4a35cd 100644 --- a/source/blender/python/bmesh/bmesh_py_ops_call.c +++ b/source/blender/python/bmesh/bmesh_py_ops_call.c @@ -48,11 +48,13 @@ static int bpy_bm_op_as_py_error(BMesh *bm) { if (BMO_error_occurred(bm)) { + /* note: we could have multiple errors */ const char *errmsg; if (BMO_error_get(bm, &errmsg, NULL)) { PyErr_Format(PyExc_RuntimeError, "bmesh operator: %.200s", errmsg); + BMO_error_clear(bm); return -1; } } @@ -692,6 +694,9 @@ PyObject *BPy_BMO_call(BPy_BMeshOpFunc *self, PyObject *args, PyObject *kw) { BPY_BM_CHECK_OBJ(py_bm); bm = py_bm->bm; + + /* could complain about entering with exceptions... */ + BMO_error_clear(bm); } else { PyErr_SetString(PyExc_TypeError, diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c index 0abff03da46..b95db945eb1 100644 --- a/source/blender/python/bmesh/bmesh_py_types.c +++ b/source/blender/python/bmesh/bmesh_py_types.c @@ -50,6 +50,8 @@ #include "bmesh_py_types_customdata.h" #include "bmesh_py_types_meshdata.h" +static void bm_dealloc_editmode_warn(BPy_BMesh *self); + /* Common Flags * ************ */ @@ -847,6 +849,8 @@ static PyObject *bpy_bmesh_free(BPy_BMesh *self) if (self->bm) { BMesh *bm = self->bm; + bm_dealloc_editmode_warn(self); + if ((self->flag & BPY_BMFLAG_IS_WRAPPED) == 0) { BM_mesh_free(bm); } @@ -2828,6 +2832,8 @@ static void bpy_bmesh_dealloc(BPy_BMesh *self) /* have have been freed by bmesh */ if (bm) { + bm_dealloc_editmode_warn(self); + BM_data_layer_free(bm, &bm->vdata, CD_BM_ELEM_PYPTR); BM_data_layer_free(bm, &bm->edata, CD_BM_ELEM_PYPTR); BM_data_layer_free(bm, &bm->pdata, CD_BM_ELEM_PYPTR); @@ -3638,3 +3644,51 @@ char *BPy_BMElem_StringFromHType(const char htype) static char ret[32]; return BPy_BMElem_StringFromHType_ex(htype, ret); } + + +/* -------------------------------------------------------------------- */ +/* keep at bottom */ +/* BAD INCLUDES */ + +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_tessmesh.h" +#include "DNA_scene_types.h" +#include "DNA_object_types.h" +#include "DNA_mesh_types.h" +#include "MEM_guardedalloc.h" + +/* there are cases where this warning isnt needed, otherwise it could be made into an error */ +static void bm_dealloc_warn(const char *mesh_name) +{ + PySys_WriteStdout("Modified BMesh '%.200s' from a wrapped editmesh is freed without a call " + "to bmesh.update_edit_mesh(mesh, destructive=True), this is will likely cause a crash\n", + mesh_name); +} + +/* this function is called on free, it should stay quite fast */ +static void bm_dealloc_editmode_warn(BPy_BMesh *self) +{ + if (self->flag & BPY_BMFLAG_IS_WRAPPED) { + /* likely editmesh */ + BMesh *bm = self->bm; + Scene *scene; + for (scene = G.main->scene.first; scene; scene = scene->id.next) { + Base *base = scene->basact; + if (base && base->object->type == OB_MESH) { + Mesh *me = base->object->data; + BMEditMesh *em = me->edit_btmesh; + if (em && em->bm == bm) { + /* not foolproof, scripter may have added/removed verts */ + if (((em->vert_index && (MEM_allocN_len(em->vert_index) / sizeof(*em->vert_index)) != bm->totvert)) || + ((em->edge_index && (MEM_allocN_len(em->edge_index) / sizeof(*em->edge_index)) != bm->totedge)) || + ((em->face_index && (MEM_allocN_len(em->face_index) / sizeof(*em->face_index)) != bm->totface))) + { + bm_dealloc_warn(me->id.name + 2); + break; + } + } + } + } + } +} diff --git a/source/blender/python/intern/bpy_app_translations.c b/source/blender/python/intern/bpy_app_translations.c index b6d2f624229..7c89972b486 100644 --- a/source/blender/python/intern/bpy_app_translations.c +++ b/source/blender/python/intern/bpy_app_translations.c @@ -74,7 +74,7 @@ typedef struct GHashKey { static GHashKey *_ghashutil_keyalloc(const void *msgctxt, const void *msgid) { GHashKey *key = MEM_mallocN(sizeof(GHashKey), "Py i18n GHashKey"); - key->msgctxt = BLI_strdup(msgctxt ? msgctxt : BLF_I18NCONTEXT_DEFAULT_BPY_INTERN); + key->msgctxt = BLI_strdup(msgctxt ? msgctxt : BLF_I18NCONTEXT_DEFAULT_BPY); key->msgid = BLI_strdup(msgid); return key; } @@ -195,7 +195,7 @@ static void _build_translations_cache(PyObject *py_messages, const char *locale) else { PyObject *tmp = PyTuple_GET_ITEM(pykey, 0); if (tmp == Py_None) { - msgctxt = BLF_I18NCONTEXT_DEFAULT; + msgctxt = BLF_I18NCONTEXT_DEFAULT_BPY; } else if (PyUnicode_Check(tmp)) { msgctxt = _PyUnicode_AsString(tmp); @@ -288,9 +288,7 @@ const char *BPY_app_translations_py_pgettext(const char *msgctxt, const char *ms _ghashutil_keyfree((void *)key); - if (tmp) - return tmp; - return msgid; + return tmp ? tmp : msgid; #undef STATIC_LOCALE_SIZE } @@ -435,8 +433,8 @@ static PyObject *app_translations_contexts_make(void) PyDoc_STRVAR(app_translations_contexts_doc, "A named tuple containing all pre-defined translation contexts.\n" - "WARNING: do not use the \"" BLF_I18NCONTEXT_DEFAULT_BPY_INTERN "\" context, it is internally assimilated as the " - "default one!\n" + "WARNING: Never use a (new) context starting with \"" BLF_I18NCONTEXT_DEFAULT_BPY "\", it would be internally " + "assimilated as the default one!\n" ); PyDoc_STRVAR(app_translations_contexts_C_to_py_doc, @@ -495,6 +493,39 @@ PyGetSetDef app_translations_getseters[] = { {NULL} }; +/* pgettext helper. */ +static PyObject *_py_pgettext(PyObject *args, PyObject *kw, const char *(*_pgettext)(const char *, const char *)) +{ + static const char *kwlist[] = {"msgid", "msgctxt", NULL}; + +#ifdef WITH_INTERNATIONAL + char *msgid, *msgctxt = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kw, + "s|z:bpy.app.translations.pgettext", + (char **)kwlist, &msgid, &msgctxt)) + { + return NULL; + } + + return PyUnicode_FromString((*_pgettext)(msgctxt ? msgctxt : BLF_I18NCONTEXT_DEFAULT, msgid)); +#else + PyObject *msgid, *msgctxt; + (void)_pgettext; + + if (!PyArg_ParseTupleAndKeywords(args, kw, + "O|O:bpy.app.translations.pgettext", + (char **)kwlist, &msgid, &msgctxt)) + { + return NULL; + } + + Py_INCREF(msgid); + + return msgid; +#endif +} + PyDoc_STRVAR(app_translations_pgettext_doc, ".. method:: pgettext(msgid, msgctxt)\n" "\n" @@ -502,7 +533,8 @@ PyDoc_STRVAR(app_translations_pgettext_doc, " NOTE: The (msgid, msgctxt) parameter orders has been switched compared to gettext function, to allow\n" " single-parameter calls (context then defaults to BLF_I18NCONTEXT_DEFAULT).\n" " NOTE: You should really rarely need to use this function in regular addon code, as all translation should be\n" -" handled by Blender internal code.\n" +" handled by Blender internal code. The only exception are string containing formatting (like \"File: %r\"),\n" +" but you should rather use pgettext_iface/_tip in those cases!\n" " Note: Does nothing when Blender is built without internationalization support (hence always returns msgid).\n" "\n" " :arg msgid: The string to translate.\n" @@ -515,26 +547,45 @@ PyDoc_STRVAR(app_translations_pgettext_doc, ); static PyObject *app_translations_pgettext(BlenderAppTranslations *UNUSED(self), PyObject *args, PyObject *kw) { - /* Note we could optimize this a bit when WITH_INTERNATIONAL is not defined, but don't think "code complexity" would - * be worth it, as this func should not often be used! - */ - /* XXX This code fails with scons when WITH_INTERNATIONAL is not defined, at link time, stating that BLF_pgettext - * is undefined... So using #ifdef after all, rather than removing scons from blender trunk! - */ - static const char *kwlist[] = {"msgid", "msgctxt", NULL}; - char *msgid, *msgctxt = NULL; + return _py_pgettext(args, kw, BLF_pgettext); +} - if (!PyArg_ParseTupleAndKeywords(args, kw, "s|z:bpy.app.translations.pgettext", (char **)kwlist, - &msgid, &msgctxt)) - { - return NULL; - } +PyDoc_STRVAR(app_translations_pgettext_iface_doc, +".. method:: pgettext_iface(msgid, msgctxt)\n" +"\n" +" Try to translate the given msgid (with optional msgctxt), if labels' translation is enabled.\n" +" NOTE: See pgettext notes.\n" +"\n" +" :arg msgid: The string to translate.\n" +" :type msgid: string\n" +" :arg msgctxt: The translation context.\n" +" :type msgctxt: string or None\n" +" :default msgctxt: BLF_I18NCONTEXT_DEFAULT value.\n" +" :return: The translated string (or msgid if no translation was found).\n" +"\n" +); +static PyObject *app_translations_pgettext_iface(BlenderAppTranslations *UNUSED(self), PyObject *args, PyObject *kw) +{ + return _py_pgettext(args, kw, BLF_translate_do_iface); +} -#ifdef WITH_INTERNATIONAL - return PyUnicode_FromString(BLF_pgettext(msgctxt ? msgctxt : BLF_I18NCONTEXT_DEFAULT, msgid)); -#else - return PyUnicode_FromString(msgid); -#endif +PyDoc_STRVAR(app_translations_pgettext_tip_doc, +".. method:: pgettext(msgid, msgctxt)\n" +"\n" +" Try to translate the given msgid (with optional msgctxt), if tooltips' translation is enabled.\n" +" NOTE: See pgettext notes.\n" +"\n" +" :arg msgid: The string to translate.\n" +" :type msgid: string\n" +" :arg msgctxt: The translation context.\n" +" :type msgctxt: string or None\n" +" :default msgctxt: BLF_I18NCONTEXT_DEFAULT value.\n" +" :return: The translated string (or msgid if no translation was found).\n" +"\n" +); +static PyObject *app_translations_pgettext_tip(BlenderAppTranslations *UNUSED(self), PyObject *args, PyObject *kw) +{ + return _py_pgettext(args, kw, BLF_translate_do_tooltip); } PyDoc_STRVAR(app_translations_locale_explode_doc, @@ -575,6 +626,10 @@ PyMethodDef app_translations_methods[] = { app_translations_py_messages_unregister_doc}, {(char *)"pgettext", (PyCFunction)app_translations_pgettext, METH_VARARGS | METH_KEYWORDS | METH_STATIC, app_translations_pgettext_doc}, + {(char *)"pgettext_iface", (PyCFunction)app_translations_pgettext_iface, METH_VARARGS | METH_KEYWORDS | METH_STATIC, + app_translations_pgettext_iface_doc}, + {(char *)"pgettext_tip", (PyCFunction)app_translations_pgettext_tip, METH_VARARGS | METH_KEYWORDS | METH_STATIC, + app_translations_pgettext_tip_doc}, {(char *)"locale_explode", (PyCFunction)app_translations_locale_explode, METH_VARARGS | METH_KEYWORDS | METH_STATIC, app_translations_locale_explode_doc}, {NULL} |