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>2011-11-03 10:53:52 +0400
committerCampbell Barton <ideasman42@gmail.com>2011-11-03 10:53:52 +0400
commite2393d11090765caf987e5ef8e2e688d80c0e64d (patch)
tree2aa909746eb9c11fb47c60740f80fb197384565b /source/blender/python/intern/bpy_app_handlers.c
parent7d7977658ad12a940597da5b78ce70e4e5081f4b (diff)
ability to have permanent callbacks that stay active when new blend files are loaded.
this works by tagging functions, eg: def my_func(scene): pass bpy.app.handlers.permanent_tag(my_func, True) # <-- important bit bpy.app.handlers.frame_change_pre.append(my_func)
Diffstat (limited to 'source/blender/python/intern/bpy_app_handlers.c')
-rw-r--r--source/blender/python/intern/bpy_app_handlers.c113
1 files changed, 110 insertions, 3 deletions
diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c
index e7f74569f1a..9ca0e71e71d 100644
--- a/source/blender/python/intern/bpy_app_handlers.c
+++ b/source/blender/python/intern/bpy_app_handlers.c
@@ -49,6 +49,11 @@ static PyStructSequence_Field app_cb_info_fields[]= {
{(char *)"save_post", NULL},
{(char *)"scene_update_pre", NULL},
{(char *)"scene_update_post", NULL},
+
+ /* sets the permanent tag */
+# define APP_CB_OTHER_FIELDS 1
+ {(char *)"permanent_tag", NULL},
+
{NULL}
};
@@ -65,6 +70,71 @@ static PyStructSequence_Desc app_cb_info_desc= {
#endif
*/
+/* --------------------------------------------------------------------------*/
+/* permanent tagging code */
+#define PERMINENT_CB_ID "_bpy_permanent_tag"
+
+PyDoc_STRVAR(bpy_app_handlers_permanent_tag_doc,
+".. function:: permanent_tag(func, state=True)\n"
+"\n"
+" Set the function as being permanent so its not cleared when new blend files are loaded.\n"
+"\n"
+" :arg func: The function to set as permanent.\n"
+" :type func: function\n"
+" :arg state: Set the permanent state to True or False.\n"
+" :type state: bool\n"
+" :return: the function argument\n"
+" :rtype: function\n"
+);
+
+static PyObject *bpy_app_handlers_permanent_tag(PyObject *UNUSED(self), PyObject *args)
+{
+ PyObject *value;
+ int state= 1;
+
+ if(!PyArg_ParseTuple(args, "O|i:permanent_tag", &value, &state))
+ return NULL;
+
+ if (PyFunction_Check(value)) {
+ PyObject **dict_ptr= _PyObject_GetDictPtr(value);
+ if (dict_ptr == NULL) {
+ PyErr_SetString(PyExc_ValueError,
+ "bpy.app.handlers.permanent_tag wasn't able to "
+ "get the dictionary from the function passed");
+ return NULL;
+ }
+ else {
+ if (state) {
+ /* set id */
+ if (*dict_ptr == NULL) {
+ *dict_ptr= PyDict_New();
+ }
+
+ PyDict_SetItemString(*dict_ptr, PERMINENT_CB_ID, Py_None);
+ }
+ else {
+ /* clear id */
+ if (*dict_ptr) {
+ PyDict_DelItemString(*dict_ptr, PERMINENT_CB_ID);
+ }
+ }
+ }
+
+ Py_INCREF(value);
+ return value;
+ }
+ else {
+ PyErr_SetString(PyExc_ValueError,
+ "bpy.app.handlers.permanent_tag expected a function");
+ return NULL;
+ }
+}
+
+static PyMethodDef meth_bpy_app_handlers_permanent_tag= {"permanent_tag", (PyCFunction)bpy_app_handlers_permanent_tag, METH_VARARGS, bpy_app_handlers_permanent_tag_doc};
+
+
+
+
static PyObject *py_cb_array[BLI_CB_EVT_TOT]= {NULL};
static PyObject *make_app_cb_info(void)
@@ -83,10 +153,13 @@ static PyObject *make_app_cb_info(void)
}
PyStructSequence_SET_ITEM(app_cb_info, pos, (py_cb_array[pos]= PyList_New(0)));
}
- if (app_cb_info_fields[pos].name != NULL) {
+ if (app_cb_info_fields[pos + APP_CB_OTHER_FIELDS].name != NULL) {
Py_FatalError("invalid callback slots 2");
}
+ /* custom function */
+ PyStructSequence_SET_ITEM(app_cb_info, pos++, (PyObject *)PyCFunction_New(&meth_bpy_app_handlers_permanent_tag, NULL));
+
return app_cb_info;
}
@@ -120,12 +193,46 @@ PyObject *BPY_app_handlers_struct(void)
return ret;
}
-void BPY_app_handlers_reset(void)
+void BPY_app_handlers_reset(const short do_all)
{
int pos= 0;
+ if (do_all) {
for (pos= 0; pos < BLI_CB_EVT_TOT; pos++) {
- PyList_SetSlice(py_cb_array[pos], 0, PY_SSIZE_T_MAX, NULL);
+ /* clear list */
+ PyList_SetSlice(py_cb_array[pos], 0, PY_SSIZE_T_MAX, NULL);
+ }
+ }
+ else {
+ /* save string conversion thrashing */
+ PyObject *perm_id_str= PyUnicode_FromString(PERMINENT_CB_ID);
+
+ for (pos= 0; pos < BLI_CB_EVT_TOT; pos++) {
+ /* clear only items without PERMINENT_CB_ID */
+ PyObject *ls= py_cb_array[pos];
+ Py_ssize_t i;
+
+ PyObject *item;
+ PyObject **dict_ptr;
+
+ for(i= PyList_GET_SIZE(ls) - 1; i >= 0; i--) {
+
+ if ( (PyFunction_Check((item= PyList_GET_ITEM(ls, i)))) &&
+ (dict_ptr= _PyObject_GetDictPtr(item)) &&
+ (*dict_ptr) &&
+ (PyDict_GetItem(*dict_ptr, perm_id_str) != NULL))
+ {
+ /* keep */
+ }
+ else {
+ /* remove */
+ /* PySequence_DelItem(ls, i); */ /* more obvious buw slower */
+ PyList_SetSlice(ls, i, i + 1, NULL);
+ }
+ }
+ }
+
+ Py_DECREF(perm_id_str);
}
}