[Bf-committers] [Bf-blender-cvs] SVN commit: /data/svn/bf-blender [11387] trunk/blender/source/blender: = Draw Module Fixed=
Diego Hernan Borghetti
bdiego at gmail.com
Fri Jul 27 16:03:29 CEST 2007
On Thu, 26 Jul 2007, Joe Eagar wrote:
> BTW, this should be merged into the stable branch before the final 2.45
> release, but I suppose people should have a few days first just in case
> there's any bugs or problems I didn't catch.
>
> Joe
>
> Joseph Eagar wrote:
>> Revision: 11387
>> http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=11387
>> Author: joeedh
>> Date: 2007-07-27 08:14:25 +0200 (Fri, 27 Jul 2007)
>>
>> Log Message:
>> -----------
>> =Draw Module Fixed=
>>
>> 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.
>>
>> Modified Paths:
>> --------------
>> trunk/blender/source/blender/blenloader/intern/writefile.c
>> trunk/blender/source/blender/makesdna/DNA_space_types.h
>> trunk/blender/source/blender/python/BPY_extern.h
>> trunk/blender/source/blender/python/api2_2x/Draw.c
>> trunk/blender/source/blender/python/api2_2x/Draw.h
>> trunk/blender/source/blender/src/drawscript.c
>> trunk/blender/source/blender/src/space.c
>>
>> Modified: trunk/blender/source/blender/blenloader/intern/writefile.c
>> ===================================================================
>> --- trunk/blender/source/blender/blenloader/intern/writefile.c 2007-07-27 05:06:05 UTC (rev 11386)
>> +++ trunk/blender/source/blender/blenloader/intern/writefile.c 2007-07-27 06:14:25 UTC (rev 11387)
>> @@ -1582,6 +1582,8 @@
>> 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) {
>>
>> Modified: trunk/blender/source/blender/makesdna/DNA_space_types.h
>> ===================================================================
>> --- trunk/blender/source/blender/makesdna/DNA_space_types.h 2007-07-27 05:06:05 UTC (rev 11386)
>> +++ trunk/blender/source/blender/makesdna/DNA_space_types.h 2007-07-27 06:14:25 UTC (rev 11387)
>> @@ -292,9 +292,10 @@
>> struct ScrArea *area;
>> struct Script *script;
>>
>> - int pad2;
>> short flags, menunr;
>> -
>> + int pad1;
>> +
>> + void *but_refs;
>> } SpaceScript;
>>
>> typedef struct SpaceTime {
>>
>> Modified: trunk/blender/source/blender/python/BPY_extern.h
>> ===================================================================
>> --- trunk/blender/source/blender/python/BPY_extern.h 2007-07-27 05:06:05 UTC (rev 11386)
>> +++ trunk/blender/source/blender/python/BPY_extern.h 2007-07-27 06:14:25 UTC (rev 11387)
>> @@ -51,6 +51,25 @@
>> 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]);
>>
>> Modified: trunk/blender/source/blender/python/api2_2x/Draw.c
>> ===================================================================
>> --- trunk/blender/source/blender/python/api2_2x/Draw.c 2007-07-27 05:06:05 UTC (rev 11386)
>> +++ trunk/blender/source/blender/python/api2_2x/Draw.c 2007-07-27 06:14:25 UTC (rev 11387)
>> @@ -134,19 +134,13 @@
>> /* 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 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 @@
>>
>> 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 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 @@
>> 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 @@
>> 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 @@
>>
>> 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 @@
>> 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,33 +838,51 @@
>> 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);
>> + }
>> }
>> -static void set_pycallback(uiBut *ubut, PyObject *callback)
>> +
>> +void BPy_Set_DrawButtonsList(void *list)
>> {
>> - 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);
>> + M_Button_List = list;
>> }
>>
>> +/*this MUST be called after doing UI stuff.*/
>> +void BPy_Free_DrawButtonsList(void)
>> +{
>> + /*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 )
>> {
>> SpaceScript *sc;
>> @@ -1047,6 +1071,7 @@
>> return (PyObject*) but;
>> }
>>
>> +
>> static PyObject *Method_UIBlock( PyObject * self, PyObject * args )
>> {
>> PyObject *val = NULL;
>> @@ -1060,13 +1085,15 @@
>> 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 @@
>> }
>> 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 @@
>> 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 @@
>> 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 @@
>> 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);
>>
>> @@ Diff output truncated at 10240 characters. @@
>>
>> _______________________________________________
>> Bf-blender-cvs mailing list
>> Bf-blender-cvs at blender.org
>> http://lists.blender.org/mailman/listinfo/bf-blender-cvs
>>
>>
>
> _______________________________________________
> Bf-committers mailing list
> Bf-committers at blender.org
> http://lists.blender.org/mailman/listinfo/bf-committers
>
Hi Joe:
Thanks to point this, to me, i stop merge things from trunk, so all the RC
are build without changes. When all the rc are finish (OSX Intel, Irix and
Linux 64 (alut problem)), i start merge again.
--
Diego
More information about the Bf-committers
mailing list