=Draw Module Fixed=
authorJoseph Eagar <joeedh@gmail.com>
Fri, 27 Jul 2007 06:14:25 +0000 (06:14 +0000)
committerJoseph Eagar <joeedh@gmail.com>
Fri, 27 Jul 2007 06:14:25 +0000 (06:14 +0000)
This commit fixes the Draw module.  All buttons/widgets created via the Draw
module in a SpaceScript area are now inserted into a global list attached to
the SpaceScript data.  This list is cleared before each draw, when freeing
the space, and when the area is switched to another space.c

This is necessary to prevent Blender's internal UI code from getting invalid
pointers to python data.  In addition, it allows storing widget tooltips
inside the python Button objects, which solves that little bit of stupidity.

Note that this reverts the previous weaklist solution.  In fact, I had to go
over each previous commit by Campbell after this code originally branched
before the weaklist commit and re-add each commit.  So if anything is
missing, just tell me, or feel free to re-add it.

source/blender/blenloader/intern/writefile.c
source/blender/makesdna/DNA_space_types.h
source/blender/python/BPY_extern.h
source/blender/python/api2_2x/Draw.c
source/blender/python/api2_2x/Draw.h
source/blender/src/drawscript.c
source/blender/src/space.c

index ca63b860f6c828106e1ab10ea4869d81fb994c2d..925233b4d77ec3c4dbfd4dc8bd4768940b19037c 100644 (file)
@@ -1582,6 +1582,8 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
                                        writestruct(wd, DATA, "SpaceText", 1, sl);
                                }
                                else if(sl->spacetype==SPACE_SCRIPT) {
+                                       SpaceScript *sc = (SpaceScript*)sl;
+                                       sc->but_refs = NULL;
                                        writestruct(wd, DATA, "SpaceScript", 1, sl);
                                }
                                else if(sl->spacetype==SPACE_ACTION) {
index 65be09caf35fe543f700b6591de6157ed042a0e6..e7839f49caeb59cbb6d0529735ad7e63159887b3 100644 (file)
@@ -292,9 +292,10 @@ typedef struct SpaceScript {
        struct ScrArea *area;
        struct Script *script;
 
-       int pad2;
        short flags, menunr;
-
+       int pad1;
+       
+       void *but_refs;
 } SpaceScript;
 
 typedef struct SpaceTime {
index 0d466d5af7e188f37af6c84e57db62dc28c8534c..ee7afe7dcf62a413f0d6c0a520301f832438fc6e 100644 (file)
@@ -51,6 +51,25 @@ struct bPythonConstraint; /* DNA_constraint_types.h */
 extern "C" {
 #endif
 
+       /*These two next functions are important for making sure the Draw module
+         works correctly.  Before calling any gui callback using the Draw module,
+         the following code must be executed:
+         
+               if (some_drawspace_pylist) {
+                       BPy_Set_DrawButtonsList(some_drawspace_pylist->but_refs);
+                       BPy_Free_DrawButtonsList();
+               }
+               some_drawspace_pylist = PyList_New(0);
+               BPy_Set_DrawButtonsList(some_drawspace_pylist);
+
+      Also, BPy_Free_DrawButtonsList() must be called as necassary when a drawspace
+      with python callbacks is destroyed.
+      
+      This is necassary to avoid blender buttons storing invalid pointers to freed
+      python data.*/
+       void BPy_Set_DrawButtonsList(void *list);
+       void BPy_Free_DrawButtonsList(void);
+       
        void BPY_pyconstraint_eval(struct bPythonConstraint *con, float ownermat[][4], float targetmat[][4]);
        void BPY_pyconstraint_settings(void *arg1, void *arg2);
        int BPY_pyconstraint_targets(struct bPythonConstraint *con, float targetmat[][4]);
index ea02fd57fe929cd9aed696d6780904272c4deb22..db8b6305dc73f253167cb0c115a41ef3b3944590 100644 (file)
@@ -134,19 +134,13 @@ static PyObject *Method_Image( PyObject * self, PyObject * args);
 /* CLEVER NUMBUT */
 static PyObject *Method_PupBlock( PyObject * self, PyObject * args );
 
-PyObject * pycallback_weakref_dealloc(PyObject *self, PyObject *weakref);
-/* python callable */
-PyObject * pycallback_weakref_dealloc__pyfunc;
-
 static uiBlock *Get_uiBlock( void );
+
 static void py_slider_update( void *butv, void *data2_unused );
 
 /* hack to get 1 block for the UIBlock, only ever 1 at a time */
 static uiBlock *uiblock=NULL;
 
-/* store weakref's to callbacks here */
-static PyObject *callback_list; 
-
 static char Draw_doc[] = "The Blender.Draw submodule";
 
 static char Method_UIBlock_doc[] = "(drawfunc, x,y) - Popup dialog where buttons can be drawn (expemental)";
@@ -362,6 +356,12 @@ Warning: On cancel, the value objects are brought back to there previous values,
 
 static char Method_Exit_doc[] = "() - Exit the windowing interface";
 
+/*This is needed for button callbacks.  Any button that uses a callback gets added to this list.
+  On the C side of drawing begin, this list should be cleared.
+  Each entry is a tuple of the form (button, callback py object)
+*/
+PyObject *M_Button_List = NULL;
+
 /*
 * here we engage in some macro trickery to define the PyMethodDef table
 */
@@ -602,7 +602,13 @@ static PyObject *Button_richcmpr(PyObject *objectA, PyObject *objectB, int compa
 
 static Button *newbutton( void )
 {
-       return ( Button * ) PyObject_NEW( Button, &Button_Type );
+       Button *but = NULL;
+       
+       but = ( Button * ) PyObject_NEW( Button, &Button_Type );
+       but->tooltip[0] = 0; /*NULL-terminate tooltip string*/
+       but->tooltip[255] = 0; /*necassary to insure we always have a NULL-terminated string, as
+                                according to the docs strncpy doesn't do this for us.*/
+       return but;
 }
 
 /* GUI interface routines */
@@ -623,6 +629,10 @@ static void exit_pydraw( SpaceScript * sc, short err )
                scrarea_queue_redraw( sc->area );
        }
 
+       BPy_Set_DrawButtonsList(sc->but_refs);
+       BPy_Free_DrawButtonsList(); /*clear all temp button references*/
+       sc->but_refs = NULL;
+       
        Py_XDECREF( ( PyObject * ) script->py_draw );
        Py_XDECREF( ( PyObject * ) script->py_event );
        Py_XDECREF( ( PyObject * ) script->py_button );
@@ -676,6 +686,13 @@ void BPY_spacescript_do_pywin_draw( SpaceScript * sc )
                            UI_HELV, curarea->win );
 
        if( script->py_draw ) {
+               if (sc->but_refs) {
+                       BPy_Set_DrawButtonsList(sc->but_refs);
+                       BPy_Free_DrawButtonsList(); /*clear all temp button references*/
+               }
+               sc->but_refs = PyList_New(0);
+               BPy_Set_DrawButtonsList(sc->but_refs);
+               
                glPushAttrib( GL_ALL_ATTRIB_BITS );
                exec_callback( sc, script->py_draw, Py_BuildValue( "()" ) );
                glPopAttrib(  );
@@ -717,10 +734,7 @@ void BPY_spacescript_do_pywin_event( SpaceScript * sc, unsigned short event,
 
                if (event == UI_BUT_EVENT) {
                        /* check that event is in free range for script button events;
-                        * read the comment before check_button_event() below to understand
-                        * 
-                        * This will never run from UIBlock so no need to check if uiblock==NULL
-                        * And only sub EXPP_BUTTON_EVENTS_OFFSET in that case */
+                        * read the comment before check_button_event() below to understand */
                        if (val >= EXPP_BUTTON_EVENTS_OFFSET && val < 0x4000)
                                spacescript_do_pywin_buttons(sc, val - EXPP_BUTTON_EVENTS_OFFSET);
                        return;
@@ -758,14 +772,6 @@ static void exec_but_callback(void *pyobj, void *data)
        if (callback==NULL || callback == Py_None)
                return;
        
-       if (callback) {
-               if (!PySequence_Contains(callback_list, callback)) {
-                       printf("Error, the callback is out of scope.\n\tmake the callback global to resolve this.\n");
-                       return;
-               }
-               callback = PyWeakref_GetObject(callback);
-       }
-
        /* Button types support
        case MENU:      
        case TEX:
@@ -832,31 +838,49 @@ static void exec_but_callback(void *pyobj, void *data)
        Py_XDECREF( result );
 }
 
-PyObject * pycallback_weakref_dealloc(PyObject *self, PyObject *weakref)
+/*note that this function populates the drawbutton ref lists.*/
+static void set_pycallback(uiBut *ubut, PyObject *callback, Button *but)
 {
-       int i = PySequence_Index(callback_list, weakref);
-       if (i==-1) {
-               printf("callback weakref internal error, weakref not in list\n\tthis should never happen.\n");
-               return NULL;
+       PyObject *tuple;
+       if (!callback || !PyCallable_Check(callback)) {
+               if (M_Button_List && but) {
+                       PyList_Append(M_Button_List, (PyObject*)but);
+               }
+               return;
        }
-       PySequence_DelItem(callback_list, i);
-       Py_RETURN_NONE;
+       
+       if (M_Button_List) {
+               if (but) tuple = PyTuple_New(2);
+               else tuple = PyTuple_New(1);
+               
+               /*the tuple API mandates this*/
+               Py_XINCREF(callback);
+               Py_XINCREF(but); /*this checks for NULL*/
+               
+               PyTuple_SET_ITEM(tuple, 0, callback);
+               if (but) PyTuple_SET_ITEM(tuple, 1, (PyObject*)but);
+               
+               PyList_Append(M_Button_List, tuple);
+               Py_DECREF(tuple); /*we have to do this to aovid double references.*/
+               
+               uiButSetFunc(ubut, exec_but_callback, callback, ubut);
+       }
+}
+
+void BPy_Set_DrawButtonsList(void *list)
+{
+       M_Button_List = list;
 }
-static void set_pycallback(uiBut *ubut, PyObject *callback)
+
+/*this MUST be called after doing UI stuff.*/
+void BPy_Free_DrawButtonsList(void)
 {
-       PyObject *weakref;
-       if (!callback || !PyCallable_Check(callback)) return;
-       
-       /* This works in most cases except where there are local functions
-        * that are deallocated so we must use weakrefs, will complain rather then crashing */
-       /*uiButSetFunc(ubut, exec_but_callback, callback, ubut);*/
-       
-       weakref = PyWeakref_NewRef(callback, pycallback_weakref_dealloc__pyfunc);
-       PyList_Append(callback_list, weakref);
-       Py_DECREF(weakref);
-       
-       /*printf("adding weakref, totlength %i\n", PyList_Size(callback_list));*/
-       uiButSetFunc(ubut, exec_but_callback, weakref, ubut);
+       /*Clear the list.*/
+       if (M_Button_List) {
+               PyList_SetSlice(M_Button_List, 0, PyList_Size(M_Button_List), NULL);
+               Py_DECREF(M_Button_List);
+               M_Button_List = NULL;
+       }
 }
 
 static PyObject *Method_Exit( PyObject * self )
@@ -1047,6 +1071,7 @@ static PyObject *Method_Create( PyObject * self, PyObject * args )
        return (PyObject*) but;
 }
 
+
 static PyObject *Method_UIBlock( PyObject * self, PyObject * args )
 {
        PyObject *val = NULL;
@@ -1060,13 +1085,15 @@ static PyObject *Method_UIBlock( PyObject * self, PyObject * args )
        if (uiblock)
                return EXPP_ReturnPyObjError( PyExc_RuntimeError,
              "cannot run more then 1 UIBlock at a time" );
+
+       BPy_Set_DrawButtonsList(PyList_New(0));
        
        mywinset(G.curscreen->mainwin);
        uiblock= uiNewBlock(&listb, "numbuts", UI_EMBOSS, UI_HELV, G.curscreen->mainwin);
        
        uiBlockSetFlag(uiblock, UI_BLOCK_LOOP|UI_BLOCK_REDRAW);
        result = PyObject_CallObject( val, Py_BuildValue( "()" ) );
-
+       
        if (!result) {
                PyErr_Print(  );
                error( "Python script error: check console" );
@@ -1076,11 +1103,17 @@ static PyObject *Method_UIBlock( PyObject * self, PyObject * args )
        }
        uiFreeBlocks(&listb);
        uiblock = NULL;
+       BPy_Free_DrawButtonsList(); /*clear all temp button references*/
        
        Py_XDECREF( result );
        Py_RETURN_NONE;
 }
 
+void Set_uiBlock(uiBlock *block)
+{
+       uiblock = block;
+}
+
 static uiBlock *Get_uiBlock( void )
 {
        char butblock[32];
@@ -1149,7 +1182,7 @@ static PyObject *Method_Button( PyObject * self, PyObject * args )
        block = Get_uiBlock(  );
        if( block ) {
                uiBut *ubut = uiDefBut( block, BUT, event, name, (short)x, (short)y, (short)w, (short)h, 0, 0, 0, 0, 0, tip );
-               set_pycallback(ubut, callback);
+               set_pycallback(ubut, callback, NULL);
        }
        Py_RETURN_NONE;
 }
@@ -1173,12 +1206,13 @@ static PyObject *Method_Menu( PyObject * self, PyObject * args )
        but = newbutton(  );
        but->type = BINT_TYPE;
        but->val.asint = def;
-
+       if (tip) strncpy(but->tooltip, tip, BPY_MAX_TOOLTIP);
+       
        block = Get_uiBlock(  );
        if( block ) {
                uiBut *ubut = uiDefButI( block, MENU, event, name, (short)x, (short)y, (short)w, (short)h,
-                          &but->val.asint, 0, 0, 0, 0, tip );
-               set_pycallback(ubut, callback);
+                          &but->val.asint, 0, 0, 0, 0, but->tooltip );
+               set_pycallback(ubut, callback, but);
        }
        return ( PyObject * ) but;
 }
@@ -1202,12 +1236,13 @@ static PyObject *Method_Toggle( PyObject * self, PyObject * args )
        but = newbutton(  );
        but->type = BINT_TYPE;
        but->val.asint = def;
-
+       if (tip) strncpy(but->tooltip, tip, BPY_MAX_TOOLTIP);
+       
        block = Get_uiBlock(  );
        if( block ) {
                uiBut *ubut = uiDefButI( block, TOG, event, name, (short)x, (short)y, (short)w, (short)h,
-                          &but->val.asint, 0, 0, 0, 0, tip );
-               set_pycallback(ubut, callback);
+                          &but->val.asint, 0, 0, 0, 0, but->tooltip );
+               set_pycallback(ubut, callback, but);
        }
        return ( PyObject * ) but;
 }
@@ -1235,12 +1270,12 @@ static void py_slider_update( void *butv, void *data2_unused )
        disable_where_script( 1 );
 
        spacescript_do_pywin_buttons( curarea->spacedata.first,
-               (unsigned short)uiButGetRetVal( but ) -  EXPP_BUTTON_EVENTS_OFFSET);
+               (unsigned short)uiButGetRetVal( but ) -  EXPP_BUTTON_EVENTS_OFFSET );
 
        /* XXX useless right now, investigate better before a bcon 5 */
        ret = M_Window_Redraw( 0, ref );
 
-       Py_DECREF(ref);
+       Py_XDECREF(ref);
        Py_XDECREF(ret);
 
        disable_where_script( 0 );
@@ -1265,10 +1300,10 @@ static PyObject *Method_Slider( PyObject * self, PyObject * args )
                                              "expected a string, five ints, three PyObjects\n\
                        and optionally int, string and callback arguments" );
 
-       UI_METHOD_ERRORCHECK;
-       
        if(realtime && uiblock)
                realtime = 0; /* realtime dosnt work with UIBlock */
+
+       UI_METHOD_ERRORCHECK;
        
        but = newbutton(  );
 
@@ -1281,17 +1316,18 @@ static PyObject *Method_Slider( PyObject * self, PyObject * args )
 
                but->type = BFLOAT_TYPE;
                but->val.asfloat = ini;
-
+               if (tip) strncpy(but->tooltip, tip, BPY_MAX_TOOLTIP);
+               
                block = Get_uiBlock(  );
                if( block ) {
                        uiBut *ubut;
                        ubut = uiDefButF( block, NUMSLI, event, name, (short)x, (short)y, (short)w,
                                          (short)h, &but->val.asfloat, min, max, 0, 0,
-                                         tip );
+                                         but->tooltip );
                        if( realtime )
                                uiButSetFunc( ubut, py_slider_update, ubut, NULL );
                        else
-                               set_pycallback(ubut, callback);
+                               set_pycallback(ubut, callback, but);
                }
        } else {
                int ini, min, max;
@@ -1302,17 +1338,18 @@ static PyObject *Method_Slider( PyObject * self, PyObject * args )
 
                but->type = BINT_TYPE;
                but->val.asint = ini;
-
+               if (tip) strncpy(but->tooltip, tip, BPY_MAX_TOOLTIP);
+               
                block = Get_uiBlock(  );
                if( block ) {
                        uiBut *ubut;
                        ubut = uiDefButI( block, NUMSLI, event, name, (short)x, (short)y, (short)w,
                                          (short)h, &but->val.asint, (float)min, (float)max, 0, 0,
-                                         tip );
+                                         but->tooltip );
                        if( realtime )
                                uiButSetFunc( ubut, py_slider_update, ubut, NULL );
                        else
-                               set_pycallback(ubut, callback);
+                               set_pycallback(ubut, callback, but);
                }
        }
        return ( PyObject * ) but;
@@ -1345,7 +1382,8 @@ another int and string as arguments" );
                "button event argument must be in the range [0, 16382]");
 
        but = newbutton(  );
-
+       if (tip) strncpy(but->tooltip, tip, BPY_MAX_TOOLTIP);
+       
        if( PyFloat_Check( inio ) )
                but->type = BFLOAT_TYPE;
        else
@@ -1361,13 +1399,13 @@ another int and string as arguments" );
                if( but->type == BFLOAT_TYPE ) {
                        but->val.asfloat = ini;
                        ubut = uiDefButF( block, SCROLL, event, "", (short)x, (short)y, (short)w, (short)h,
-                                         &but->val.asfloat, min, max, 0, 0, tip );
+                                         &but->val.asfloat, min, max, 0, 0, but->tooltip );
                        if( realtime )
                                uiButSetFunc( ubut, py_slider_update, ubut, NULL );
                } else {
                        but->val.asint = (int)ini;
                        ubut = uiDefButI( block, SCROLL, event, "", (short)x, (short)y, (short)w, (short)h,
-                                         &but->val.asint, min, max, 0, 0, tip );
+                                         &but->val.asint, min, max, 0, 0, but->tooltip );
                        if( realtime )
                                uiButSetFunc( ubut, py_slider_update, ubut, NULL );
                }
@@ -1411,12 +1449,13 @@ static PyObject *Method_ColorPicker( PyObject * self, PyObject * args )
        but->val.asvec[0] = col[0];
        but->val.asvec[1] = col[1];
        but->val.asvec[2] = col[2];
+       if (tip) strncpy(but->tooltip, tip, BPY_MAX_TOOLTIP);
        
        block = Get_uiBlock(  );
        if( block ) {
                uiBut *ubut;
-               ubut = uiDefButF( block, COL, event, "", x, y, w, h, but->val.asvec, 0, 0, 0, 0, tip);
-               set_pycallback(ubut, callback);
+               ubut = uiDefButF( block, COL, event, "", x, y, w, h, but->val.asvec, 0, 0, 0, 0, but->tooltip);
+               set_pycallback(ubut, callback, but);
        }
 
        return ( PyObject * ) but;
@@ -1450,7 +1489,8 @@ static PyObject *Method_Normal( PyObject * self, PyObject * args )
                return EXPP_ReturnPyObjError( PyExc_ValueError, USAGE_ERROR);
  
        but = newbutton();
+       if (tip) strncpy(but->tooltip, tip, BPY_MAX_TOOLTIP);
+       
        but->type = BVECTOR_TYPE;
        but->val.asvec[0] = nor[0];
        but->val.asvec[1] = nor[1];
@@ -1459,8 +1499,8 @@ static PyObject *Method_Normal( PyObject * self, PyObject * args )
        block = Get_uiBlock(  );
        if( block ) {
                uiBut *ubut;
-               ubut = uiDefButF( block, BUT_NORMAL, event, "", x, y, w, h, but->val.asvec, 0.0f, 1.0f, 0, 0, tip);
-               set_pycallback(ubut, callback);
+               ubut = uiDefButF( block, BUT_NORMAL, event, "", x, y, w, h, but->val.asvec, 0.0f, 1.0f, 0, 0, but->tooltip);
+               set_pycallback(ubut, callback, but);
        }
        
        return ( PyObject * ) but;
@@ -1486,6 +1526,7 @@ static PyObject *Method_Number( PyObject * self, PyObject * args )
        UI_METHOD_ERRORCHECK;
 
        but = newbutton(  );
+       if (tip) strncpy(but->tooltip, tip, BPY_MAX_TOOLTIP);
        block = Get_uiBlock(  );
        
        if( PyFloat_Check( inio ) ) {
@@ -1502,15 +1543,15 @@ static PyObject *Method_Number( PyObject * self, PyObject * args )
                if      (range>=1000.0f) precission=1.0f;
                else if (range>=100.0f) precission=2.0f;
                else if (range>=10.0f) precission=3.0f;
-               else precission=4.0f;
-               
+               else precission=4.0f;
+                       
                but->type = BFLOAT_TYPE;
                but->val.asfloat = ini;
 
                
                if( block )
                        ubut= uiDefButF( block, NUM, event, name, (short)x, (short)y, (short)w, (short)h,
-                                  &but->val.asfloat, min, max, 10*range, precission, tip );
+                                  &but->val.asfloat, min, max, 10*range, precission, but->tooltip );
        } else {
                int ini, min, max;
 
@@ -1523,10 +1564,10 @@ static PyObject *Method_Number( PyObject * self, PyObject * args )
 
                if( block )
                        ubut= uiDefButI( block, NUM, event, name, (short)x, (short)y, (short)w, (short)h,
-                                  &but->val.asint, (float)min, (float)max, 0, 0, tip );
+                                  &but->val.asint, (float)min, (float)max, 0, 0, but->tooltip );
        }
        
-       if (ubut) set_pycallback(ubut, callback);
+       if (ubut) set_pycallback(ubut, callback, but);
        
        return ( PyObject * ) but;
 }
@@ -1555,11 +1596,12 @@ static PyObject *Method_String( PyObject * self, PyObject * args )
 
        real_len = strlen(newstr);
        if (real_len > len) real_len = len;
-
+       
        but = newbutton(  );
        but->type = BSTRING_TYPE;
        but->slen = len;
        but->val.asstr = MEM_mallocN( len + 1, "pybutton str" );
+       if (tip) strncpy(but->tooltip, tip, BPY_MAX_TOOLTIP);
 
        BLI_strncpy( but->val.asstr, newstr, len + 1); /* adds '\0' */
        but->val.asstr[real_len] = '\0';
@@ -1570,8 +1612,8 @@ static PyObject *Method_String( PyObject * self, PyObject * args )
        block = Get_uiBlock(  );
        if( block ) {
                uiBut *ubut = uiDefBut( block, TEX, event, info_str, (short)x, (short)y, (short)w, (short)h,
-                         but->val.asstr, 0, (float)len, 0, 0, tip );
-               set_pycallback(ubut, callback);
+                         but->val.asstr, 0, (float)len, 0, 0, but->tooltip );
+               set_pycallback(ubut, callback, but);
        }
        return ( PyObject * ) but;
 }
@@ -2004,26 +2046,17 @@ static PyObject *Method_Image( PyObject * self, PyObject * args )
 
 }
 
-static PyMethodDef bpycallback_weakref_dealloc[] = {
-       {"pycallback_weakref_dealloc", pycallback_weakref_dealloc, METH_O, ""}
-};
-
 PyObject *Draw_Init( void )
 {
        PyObject *submodule, *dict;
-       
-       /* Weakref management - used for callbacks so we can
-        * tell when a callback has been removed that a UI button referenced */
-       callback_list = PyList_New(0);
-       pycallback_weakref_dealloc__pyfunc = PyCFunction_New(bpycallback_weakref_dealloc, NULL);
-       
+
        if( PyType_Ready( &Button_Type) < 0)
                Py_RETURN_NONE;
 
        submodule = Py_InitModule3( "Blender.Draw", Draw_methods, Draw_doc );
 
        dict = PyModule_GetDict( submodule );
-       
+
 #define EXPP_ADDCONST(x) \
        EXPP_dict_set_item_str(dict, #x, PyInt_FromLong(x))
 
index 31776500c80f35ba9c38232ebf6567f8bf4199b9..12712713d1dabdb958ad439347552addc6dfd081 100644 (file)
@@ -57,11 +57,13 @@ typedef struct _Button {
                char *asstr;
                float asvec[3];
        } val;
-       /*char *tooltip;*/
+       char tooltip[256];
 } Button;
 
-#define BINT_TYPE              1
-#define BFLOAT_TYPE            2
+#define BPY_MAX_TOOLTIP        255
+
+#define BINT_TYPE                      1
+#define BFLOAT_TYPE                    2
 #define BSTRING_TYPE           3
 #define BVECTOR_TYPE           4
 
index 024d83950ad9c49b166e76a45fb60555dafe4f28..b009c3b838837c1827ee76dfe0195d97ff2e5325 100644 (file)
@@ -142,6 +142,12 @@ void winqreadscriptspace(struct ScrArea *sa, void *spacedata, struct BWinEvent *
 void free_scriptspace (SpaceScript *sc)
 {
        if (!sc) return;
-
+       
+       /*free buttons references*/
+       if (sc->but_refs) {
+               BPy_Set_DrawButtonsList(sc->but_refs);
+               BPy_Free_DrawButtonsList();
+               sc->but_refs = NULL;
+       }
        sc->script = NULL;
 }
index 8e006111ad97bf76019080b1843f60501105a93a..8c74a0f46943441ef27fc31153e51c09fd3199a7 100644 (file)
@@ -6222,13 +6222,26 @@ SpaceType *spacetext_get_type(void)
 
        return st;
 }
+
+static void spacescript_change(ScrArea *sa, void *spacedata)
+{
+       SpaceScript *sc = (SpaceScript*) spacedata;
+
+       /*clear all temp button references*/
+       if (sc->but_refs) {
+               BPy_Set_DrawButtonsList(sc->but_refs);
+               BPy_Free_DrawButtonsList();
+               sc->but_refs = NULL;
+       }
+}
+
 SpaceType *spacescript_get_type(void)
 {
        static SpaceType *st = NULL;
 
        if (!st) {
                st = spacetype_new("Script");
-               spacetype_set_winfuncs(st, drawscriptspace, NULL, winqreadscriptspace);
+               spacetype_set_winfuncs(st, drawscriptspace, spacescript_change, winqreadscriptspace);
        }
 
        return st;