[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [41485] trunk/blender/source: ability to have permanent callbacks that stay active when new blend files are loaded .

Campbell Barton ideasman42 at gmail.com
Thu Nov 3 07:53:53 CET 2011


Revision: 41485
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=41485
Author:   campbellbarton
Date:     2011-11-03 06:53:52 +0000 (Thu, 03 Nov 2011)
Log Message:
-----------
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)

Modified Paths:
--------------
    trunk/blender/source/blender/python/BPY_extern.h
    trunk/blender/source/blender/python/intern/bpy_app_handlers.c
    trunk/blender/source/blender/render/intern/source/convertblender.c
    trunk/blender/source/blender/windowmanager/intern/wm_files.c
    trunk/blender/source/blender/windowmanager/intern/wm_init_exit.c
    trunk/blender/source/creator/creator.c

Modified: trunk/blender/source/blender/python/BPY_extern.h
===================================================================
--- trunk/blender/source/blender/python/BPY_extern.h	2011-11-03 04:58:11 UTC (rev 41484)
+++ trunk/blender/source/blender/python/BPY_extern.h	2011-11-03 06:53:52 UTC (rev 41485)
@@ -71,7 +71,7 @@
 void	BPY_modules_update(struct bContext *C); // XXX - annoying, need this for pointers that get out of date
 void	BPY_modules_load_user(struct bContext *C);
 
-void	BPY_app_handlers_reset(void);
+void	BPY_app_handlers_reset(const short do_all);
 
 void	BPY_driver_reset(void);
 float	BPY_driver_exec(struct ChannelDriver *driver);

Modified: trunk/blender/source/blender/python/intern/bpy_app_handlers.c
===================================================================
--- trunk/blender/source/blender/python/intern/bpy_app_handlers.c	2011-11-03 04:58:11 UTC (rev 41484)
+++ trunk/blender/source/blender/python/intern/bpy_app_handlers.c	2011-11-03 06:53:52 UTC (rev 41485)
@@ -49,6 +49,11 @@
 	{(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 @@
 #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_O, 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 @@
 		}
 		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,13 +193,47 @@
 	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);
+	}
 }
 
 /* the actual callback - not necessarily called from py */

Modified: trunk/blender/source/blender/render/intern/source/convertblender.c
===================================================================
--- trunk/blender/source/blender/render/intern/source/convertblender.c	2011-11-03 04:58:11 UTC (rev 41484)
+++ trunk/blender/source/blender/render/intern/source/convertblender.c	2011-11-03 06:53:52 UTC (rev 41485)
@@ -2391,7 +2391,7 @@
 	/* Object Size with parenting */
 	obt=obr->ob;
 	while(obt){
-		add_v3_v3v3(temp, obt->size, obt->dsize);
+		mul_v3_v3v3(temp, obt->size, obt->dsize);
 		scale[0]*=temp[0]; scale[1]*=temp[1]; scale[2]*=temp[2];
 		obt=obt->parent;
 	}

Modified: trunk/blender/source/blender/windowmanager/intern/wm_files.c
===================================================================
--- trunk/blender/source/blender/windowmanager/intern/wm_files.c	2011-11-03 04:58:11 UTC (rev 41484)
+++ trunk/blender/source/blender/windowmanager/intern/wm_files.c	2011-11-03 06:53:52 UTC (rev 41485)
@@ -408,7 +408,7 @@
 #ifdef WITH_PYTHON
 		/* run any texts that were loaded in and flagged as modules */
 		BPY_driver_reset();
-		BPY_app_handlers_reset();
+		BPY_app_handlers_reset(FALSE);
 		BPY_modules_load_user(C);
 #endif
 
@@ -538,7 +538,7 @@
 		BPY_string_exec(C, "__import__('addon_utils').reset_all()");
 
 		BPY_driver_reset();
-		BPY_app_handlers_reset();
+		BPY_app_handlers_reset(FALSE);
 		BPY_modules_load_user(C);
 	}
 #endif

Modified: trunk/blender/source/blender/windowmanager/intern/wm_init_exit.c
===================================================================
--- trunk/blender/source/blender/windowmanager/intern/wm_init_exit.c	2011-11-03 04:58:11 UTC (rev 41484)
+++ trunk/blender/source/blender/windowmanager/intern/wm_init_exit.c	2011-11-03 06:53:52 UTC (rev 41485)
@@ -61,8 +61,9 @@
 #include "BKE_sequencer.h" /* free seq clipboard */
 #include "BKE_material.h" /* clear_matcopybuf */
 
-#include "BLI_blenlib.h"
-#include "BLI_winstuff.h"
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
 
 #include "RE_engine.h"
 #include "RE_pipeline.h"		/* RE_ free stuff */
@@ -158,7 +159,7 @@
 	BPY_python_start(argc, argv);
 
 	BPY_driver_reset();
-	BPY_app_handlers_reset(); /* causes addon callbacks to be freed [#28068],
+	BPY_app_handlers_reset(FALSE); /* causes addon callbacks to be freed [#28068],
 	                           * but this is actually what we want. */
 	BPY_modules_load_user(C);
 #else

Modified: trunk/blender/source/creator/creator.c
===================================================================
--- trunk/blender/source/creator/creator.c	2011-11-03 04:58:11 UTC (rev 41484)
+++ trunk/blender/source/creator/creator.c	2011-11-03 06:53:52 UTC (rev 41485)
@@ -971,7 +971,7 @@
 #ifdef WITH_PYTHON
 		/* run any texts that were loaded in and flagged as modules */
 		BPY_driver_reset();
-		BPY_app_handlers_reset();
+		BPY_app_handlers_reset(FALSE);
 		BPY_modules_load_user(C);
 #endif
 




More information about the Bf-blender-cvs mailing list