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
 

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to