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:
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/include/BPI_script.h1
-rw-r--r--source/blender/python/BPY_interface.c3
-rw-r--r--source/blender/python/api2_2x/Draw.c91
-rw-r--r--source/blender/python/api2_2x/Window.c94
-rw-r--r--source/blender/python/api2_2x/doc/Theme.py5
-rw-r--r--source/blender/python/api2_2x/windowTheme.c23
-rw-r--r--source/blender/src/drawscript.c24
7 files changed, 167 insertions, 74 deletions
diff --git a/source/blender/include/BPI_script.h b/source/blender/include/BPI_script.h
index 243e50ecfa4..80ac8b46900 100644
--- a/source/blender/include/BPI_script.h
+++ b/source/blender/include/BPI_script.h
@@ -47,6 +47,7 @@ typedef struct Script {
void *py_draw;
void *py_event;
void *py_button;
+ void *py_browsercallback;
void *py_globaldict;
int flags, lastspace;
diff --git a/source/blender/python/BPY_interface.c b/source/blender/python/BPY_interface.c
index 912a479eef9..f79cb2065ec 100644
--- a/source/blender/python/BPY_interface.c
+++ b/source/blender/python/BPY_interface.c
@@ -527,6 +527,7 @@ int BPY_txt_do_python_Text( struct Text *text )
script->py_draw = NULL;
script->py_event = NULL;
script->py_button = NULL;
+ script->py_browsercallback = NULL;
py_dict = CreateGlobalDictionary( );
@@ -756,6 +757,7 @@ int BPY_menu_do_python( short menutype, int event )
script->py_draw = NULL;
script->py_event = NULL;
script->py_button = NULL;
+ script->py_browsercallback = NULL;
py_dict = CreateGlobalDictionary( );
@@ -915,6 +917,7 @@ void BPY_clear_script( Script * script )
Py_XDECREF( ( PyObject * ) script->py_draw );
Py_XDECREF( ( PyObject * ) script->py_event );
Py_XDECREF( ( PyObject * ) script->py_button );
+ Py_XDECREF( ( PyObject * ) script->py_browsercallback );
dict = script->py_globaldict;
diff --git a/source/blender/python/api2_2x/Draw.c b/source/blender/python/api2_2x/Draw.c
index 0c75ee22ab6..f6c5aff0db8 100644
--- a/source/blender/python/api2_2x/Draw.c
+++ b/source/blender/python/api2_2x/Draw.c
@@ -70,6 +70,11 @@
#include "interface.h"
#include "mydevice.h" /*@ for all the event constants */
+/* these delimit the free range for button events */
+#define EXPP_BUTTON_EVENTS_OFFSET 1001
+#define EXPP_BUTTON_EVENTS_MIN 0
+#define EXPP_BUTTON_EVENTS_MAX 15382 /* 16384 - 1 - OFFSET */
+
/* pointer to main dictionary defined in Blender.c */
extern PyObject *g_blenderdict;
@@ -510,18 +515,6 @@ static void spacescript_do_pywin_buttons( SpaceScript * sc,
void BPY_spacescript_do_pywin_event( SpaceScript * sc, unsigned short event,
short val, char ascii )
{
- static int menu_hack = 0;
-
- /* about menu_hack above: when a menu returns after an entry is chosen,
- * two events are generated, the second one with val = 4. We don't want
- * this second one to be passed to Python, because it can be confused with
- * some event with same number defined by the script.
- * What we do is set menu_hack to 1 if a button event occurs.
- * Then if the next one is also a button event, w/ val = 4, we discard it. */
-
- if( event != UI_BUT_EVENT || !val )
- menu_hack = 0;
-
if( event == QKEY && G.qual & ( LR_ALTKEY | LR_CTRLKEY ) ) {
/* finish script: user pressed ALT+Q or CONTROL+Q */
Script *script = sc->script;
@@ -533,27 +526,20 @@ void BPY_spacescript_do_pywin_event( SpaceScript * sc, unsigned short event,
return;
}
- if( val ) {
- if( uiDoBlocks( &curarea->uiblocks, event ) != UI_NOTHING )
- event = 0;
-
- if( event == UI_BUT_EVENT ) {
- if( menu_hack && val == UI_RETURN_OK ) { /* "false" event? */
- if ( menu_hack == 2 ) /* was last event UI_RETURN_OUT? */
- spacescript_do_pywin_buttons( sc, UI_RETURN_OUT ); /* if so, send */
- menu_hack = 0; /* clear menu_hack */
- }
- else if( val == UI_RETURN_OUT ) /* possible cancel */
- menu_hack = 2;
- else {
- menu_hack = 1;
- spacescript_do_pywin_buttons( sc, val );
- }
+ if (val) {
+
+ if (uiDoBlocks( &curarea->uiblocks, event ) != UI_NOTHING) event = 0;
+ 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 */
+ if (val >= EXPP_BUTTON_EVENTS_OFFSET && val < 0x4000)
+ spacescript_do_pywin_buttons(sc, val - EXPP_BUTTON_EVENTS_OFFSET);
+ return;
}
}
- /* Using the "event" main module var, used by scriptlinks, to pass the ascii
+ /* We use the "event" main module var, used by scriptlinks, to pass the ascii
* value to event callbacks (gui/event/button callbacks are not allowed
* inside scriptlinks, so this is ok) */
if( sc->script->py_event ) {
@@ -756,6 +742,21 @@ static uiBlock *Get_uiBlock( void )
return uiGetBlock( butblock, curarea );
}
+/* We restrict the acceptable event numbers to a proper "free" range
+ * according to other spaces in Blender.
+ * winqread***space() (space events callbacks) use short for events
+ * (called 'val' there) and we also translate by EXPP_BUTTON_EVENTS_OFFSET
+ * to get rid of unwanted events (check BPY_do_pywin_events above for
+ * explanation). This function takes care of that and proper checking: */
+static int check_button_event(int *event) {
+ if ((*event < EXPP_BUTTON_EVENTS_MIN) ||
+ (*event > EXPP_BUTTON_EVENTS_MAX)) {
+ return -1;
+ }
+ *event += EXPP_BUTTON_EVENTS_OFFSET;
+ return 0;
+}
+
static PyObject *Method_Button( PyObject * self, PyObject * args )
{
uiBlock *block;
@@ -768,6 +769,10 @@ static PyObject *Method_Button( PyObject * self, PyObject * args )
return EXPP_ReturnPyObjError( PyExc_TypeError,
"expected a string, five ints and optionally another string as arguments" );
+ if (check_button_event(&event) == -1)
+ return EXPP_ReturnPyObjError( PyExc_AttributeError,
+ "button event argument must be in the range [0, 16382]");
+
block = Get_uiBlock( );
if( block )
@@ -790,6 +795,10 @@ static PyObject *Method_Menu( PyObject * self, PyObject * args )
return EXPP_ReturnPyObjError( PyExc_TypeError,
"expected a string, six ints and optionally another string as arguments" );
+ if (check_button_event(&event) == -1)
+ return EXPP_ReturnPyObjError( PyExc_AttributeError,
+ "button event argument must be in the range [0, 16382]");
+
but = newbutton( );
but->type = 1;
but->val.asint = def;
@@ -815,6 +824,10 @@ static PyObject *Method_Toggle( PyObject * self, PyObject * args )
return EXPP_ReturnPyObjError( PyExc_TypeError,
"expected a string, six ints and optionally another string as arguments" );
+ if (check_button_event(&event) == -1)
+ return EXPP_ReturnPyObjError( PyExc_AttributeError,
+ "button event argument must be in the range [0, 16382]");
+
but = newbutton( );
but->type = 1;
but->val.asint = def;
@@ -873,6 +886,10 @@ static PyObject *Method_Slider( PyObject * self, PyObject * args )
"expected a string, five ints, three PyObjects\n\
and optionally another int and string as arguments" );
+ if (check_button_event(&event) == -1)
+ return EXPP_ReturnPyObjError( PyExc_AttributeError,
+ "button event argument must be in the range [0, 16382]");
+
but = newbutton( );
if( PyFloat_Check( inio ) ) {
@@ -932,14 +949,18 @@ static PyObject *Method_Scrollbar( PyObject * self, PyObject * args )
if( !PyArg_ParseTuple( args, "iiiiiOOO|is", &event, &x, &y, &w, &h,
&inio, &mino, &maxo, &realtime, &tip ) )
return EXPP_ReturnPyObjError( PyExc_TypeError,
- "expected five ints, three PyObjects and optionally\n\
- another int and string as arguments" );
+ "expected five ints, three PyObjects and optionally\n\
+another int and string as arguments" );
if( !PyNumber_Check( inio ) || !PyNumber_Check( inio )
|| !PyNumber_Check( inio ) )
return EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected numbers for initial, min, and max" );
+ if (check_button_event(&event) == -1)
+ return EXPP_ReturnPyObjError( PyExc_AttributeError,
+ "button event argument must be in the range [0, 16382]");
+
but = newbutton( );
if( PyFloat_Check( inio ) )
@@ -995,6 +1016,10 @@ static PyObject *Method_Number( PyObject * self, PyObject * args )
"expected a string, five ints, three PyObjects and\n\
optionally another string as arguments" );
+ if (check_button_event(&event) == -1)
+ return EXPP_ReturnPyObjError( PyExc_AttributeError,
+ "button event argument must be in the range [0, 16382]");
+
but = newbutton( );
if( PyFloat_Check( inio ) ) {
@@ -1045,6 +1070,10 @@ static PyObject *Method_String( PyObject * self, PyObject * args )
"expected a string, five ints, a string, an int and\n\
optionally another string as arguments" );
+ if (check_button_event(&event) == -1)
+ return EXPP_ReturnPyObjError( PyExc_AttributeError,
+ "button event argument must be in the range [0, 16382]");
+
if (len > (UI_MAX_DRAW_STR - 1)) {
len = UI_MAX_DRAW_STR - 1;
newstr[len] = '\0';
diff --git a/source/blender/python/api2_2x/Window.c b/source/blender/python/api2_2x/Window.c
index 41a7ad7c910..236275742be 100644
--- a/source/blender/python/api2_2x/Window.c
+++ b/source/blender/python/api2_2x/Window.c
@@ -68,9 +68,6 @@
/* See Draw.c */
extern int EXPP_disable_force_draw;
-/* Callback used by the file and image selector access functions */
-static PyObject *EXPP_FS_PyCallback = NULL;
-
/*****************************************************************************/
/* Python API function prototypes for the Window module. */
/*****************************************************************************/
@@ -453,24 +450,42 @@ static PyObject *M_Window_QRedrawAll( PyObject * self, PyObject * args )
static void getSelectedFile( char *name )
{
- PyObject *callback;
- PyObject *result;
-
- callback = EXPP_FS_PyCallback;
- result = PyObject_CallFunction( EXPP_FS_PyCallback, "s", name );
- if ((!result) && (G.f & G_DEBUG)) {
- fprintf(stderr, "BPy error: Callback call failed!\n");
+ PyObject *pycallback;
+ PyObject *result;
+ Script *script;
+
+ /* let's find the script that owns this callback */
+ script = G.main->script.first;
+ while (script) {
+ if (script->flags & SCRIPT_RUNNING) break;
+ script = script->id.next;
+ }
+
+ if (!script) {
+ if (curarea->spacetype == SPACE_SCRIPT) {
+ SpaceScript *sc = curarea->spacedata.first;
+ script = sc->script;
+ }
+ }
+
+ pycallback = script->py_browsercallback;
+
+ if (pycallback) {
+ result = PyObject_CallFunction( pycallback, "s", name );
+
+ if (!result) {
+ if (G.f & G_DEBUG)
+ fprintf(stderr, "BPy error: Callback call failed!\n");
+ }
+ else Py_DECREF(result);
+
+ if (script->py_browsercallback == pycallback)
+ script->py_browsercallback = NULL;
+ /* else another call to selector was made inside pycallback */
+
+ Py_DECREF(pycallback);
}
- Py_XDECREF(result);
- /* Catch changes of EXPP_FS_PyCallback during the callback call
- * due to calls to Blender.Window.FileSelector or
- * Blender.Window.ImageSelector inside the python callback. */
- if (callback == EXPP_FS_PyCallback) {
- Py_DECREF(EXPP_FS_PyCallback);
- EXPP_FS_PyCallback = NULL;
- } else {
- Py_DECREF(callback);
- }
+
return;
}
@@ -480,6 +495,7 @@ static PyObject *M_Window_FileSelector( PyObject * self, PyObject * args )
char *filename = G.sce;
SpaceScript *sc;
Script *script = NULL;
+ PyObject *pycallback = NULL;
int startspace = 0;
if (during_scriptlink())
@@ -490,13 +506,13 @@ static PyObject *M_Window_FileSelector( PyObject * self, PyObject * args )
return EXPP_ReturnPyObjError(PyExc_RuntimeError,
"the file selector is not available in background mode");
- if((!PyArg_ParseTuple( args, "O|ss", &EXPP_FS_PyCallback, &title, &filename))
- || (!PyCallable_Check(EXPP_FS_PyCallback)))
+ if((!PyArg_ParseTuple( args, "O|ss", &pycallback, &title, &filename))
+ || (!PyCallable_Check(pycallback)))
return EXPP_ReturnPyObjError( PyExc_AttributeError,
"\nexpected a callback function (and optionally one or two strings) "
"as argument(s)" );
- Py_XINCREF(EXPP_FS_PyCallback);
+ Py_INCREF(pycallback);
/* trick: we move to a spacescript because then the fileselector will properly
* unset our SCRIPT_FILESEL flag when the user chooses a file or cancels the
@@ -527,6 +543,12 @@ static PyObject *M_Window_FileSelector( PyObject * self, PyObject * args )
script->flags |= SCRIPT_FILESEL;
+ /* clear any previous callback (nested calls to selector) */
+ if (script->py_browsercallback) {
+ Py_DECREF((PyObject *)script->py_browsercallback);
+ }
+ script->py_browsercallback = pycallback;
+
activate_fileselect( FILE_BLENDER, title, filename, getSelectedFile );
Py_INCREF( Py_None );
@@ -539,6 +561,7 @@ static PyObject *M_Window_ImageSelector( PyObject * self, PyObject * args )
char *filename = G.sce;
SpaceScript *sc;
Script *script = NULL;
+ PyObject *pycallback = NULL;
int startspace = 0;
if (during_scriptlink())
@@ -549,14 +572,13 @@ static PyObject *M_Window_ImageSelector( PyObject * self, PyObject * args )
return EXPP_ReturnPyObjError(PyExc_RuntimeError,
"the image selector is not available in background mode");
- if( !PyArg_ParseTuple( args, "O|ss", &EXPP_FS_PyCallback, &title, &filename )
- || (!PyCallable_Check(EXPP_FS_PyCallback)))
- return ( EXPP_ReturnPyObjError
- ( PyExc_AttributeError,
- "\nexpected a callback function (and optionally one or two strings) "
- "as argument(s)" ) );
+ if( !PyArg_ParseTuple( args, "O|ss", &pycallback, &title, &filename )
+ || (!PyCallable_Check(pycallback)))
+ return EXPP_ReturnPyObjError ( PyExc_AttributeError,
+ "\nexpected a callback function (and optionally one or two strings) "
+ "as argument(s)" );
- Py_XINCREF(EXPP_FS_PyCallback);
+ Py_INCREF(pycallback);
/* trick: we move to a spacescript because then the fileselector will properly
* unset our SCRIPT_FILESEL flag when the user chooses a file or cancels the
@@ -586,6 +608,11 @@ static PyObject *M_Window_ImageSelector( PyObject * self, PyObject * args )
}
script->flags |= SCRIPT_FILESEL; /* same flag as filesel */
+ /* clear any previous callback (nested calls to selector) */
+ if (script->py_browsercallback) {
+ Py_DECREF((PyObject *)script->py_browsercallback);
+ }
+ script->py_browsercallback = pycallback;
activate_imageselect( FILE_BLENDER, title, filename, getSelectedFile );
@@ -610,12 +637,11 @@ static PyObject *M_Window_DrawProgressBar( PyObject * self, PyObject * args )
if( !PyArg_ParseTuple( args, "fs", &done, &info ) )
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
- "expected a float and a string as arguments" ) );
+ "expected a float and a string as arguments" ) );
- if( !G.background )
- retval = progress_bar( done, info );
+ retval = progress_bar( done, info );
- curarea = sa;
+ areawinset(sa->win);
return Py_BuildValue( "i", retval );
}
diff --git a/source/blender/python/api2_2x/doc/Theme.py b/source/blender/python/api2_2x/doc/Theme.py
index e2e9c74c8ed..d8be2074741 100644
--- a/source/blender/python/api2_2x/doc/Theme.py
+++ b/source/blender/python/api2_2x/doc/Theme.py
@@ -183,6 +183,11 @@ class Theme:
@cvar face_select: theme rgba var.
@cvar face_dot: theme rgba var.
@cvar normal: theme rgba var.
+ @cvar syntaxl: theme rgba var.
+ @cvar syntaxn: theme rgba var.
+ @cvar syntaxb: theme rgba var.
+ @cvar syntaxv: theme rgba var.
+ @cvar syntaxc: theme rgba var.
@type vertex_size: int
@cvar vertex_size: size of the vertices dots on screen in the range [1, 10].
@type facedot_size: int
diff --git a/source/blender/python/api2_2x/windowTheme.c b/source/blender/python/api2_2x/windowTheme.c
index 5f2e06024da..7ee6cd80a1c 100644
--- a/source/blender/python/api2_2x/windowTheme.c
+++ b/source/blender/python/api2_2x/windowTheme.c
@@ -134,9 +134,9 @@ static void ThemeSpace_dealloc( BPy_ThemeSpace * self )
else if (!strcmp(name, #attr))\
attrib = charRGBA_New(&tsp->attr[0]);
-/* Example: ELSEIF_TSP_RGBA(outline) becomes:
+/* Example: ELSEIF_TSP_RGBA(back) becomes:
* else if (!strcmp(name, "back")
- * attr = charRGBA_New(&tsp->back[0])
+ * attrib = charRGBA_New(&tsp->back[0])
*/
static PyObject *ThemeSpace_getAttr( BPy_ThemeSpace * self, char *name )
@@ -146,7 +146,7 @@ static PyObject *ThemeSpace_getAttr( BPy_ThemeSpace * self, char *name )
if( !strcmp( name, "theme" ) )
attrib = PyString_FromString( self->theme->name );
- ELSEIF_TSP_RGBA( back )
+ ELSEIF_TSP_RGBA( back )
ELSEIF_TSP_RGBA( text )
ELSEIF_TSP_RGBA( text_hi )
ELSEIF_TSP_RGBA( header )
@@ -169,19 +169,26 @@ static PyObject *ThemeSpace_getAttr( BPy_ThemeSpace * self, char *name )
ELSEIF_TSP_RGBA( face_select )
ELSEIF_TSP_RGBA( face_dot )
ELSEIF_TSP_RGBA( normal )
+ ELSEIF_TSP_RGBA( syntaxl )
+ ELSEIF_TSP_RGBA( syntaxn )
+ ELSEIF_TSP_RGBA( syntaxb )
+ ELSEIF_TSP_RGBA( syntaxv )
+ ELSEIF_TSP_RGBA( syntaxc )
else if( !strcmp( name, "vertex_size" ) )
attrib = Py_BuildValue( "i", tsp->vertex_size );
else if( !strcmp( name, "facedot_size" ) )
attrib = Py_BuildValue( "i", tsp->facedot_size );
else if( !strcmp( name, "__members__" ) )
- attrib = Py_BuildValue( "[ssssssssssssssssssssssssss]", "theme",
+ attrib = Py_BuildValue( "[sssssssssssssssssssssssssssssss]", "theme",
"back", "text", "text_hi", "header",
"panel", "shade1", "shade2", "hilite",
"grid", "wire", "select", "active",
"transform", "vertex", "vertex_select",
"edge", "edge_select", "edge_seam",
"edge_facesel", "face", "face_select",
- "face_dot", "normal", "vertex_size", "facedot_size" );
+ "face_dot", "normal",
+ "syntaxl", "syntaxn", "syntaxb", "syntaxv", "syntaxc",
+ "vertex_size", "facedot_size" );
if( attrib != Py_None )
return attrib;
@@ -199,7 +206,6 @@ static int ThemeSpace_setAttr( BPy_ThemeSpace * self, char *name,
if( !strcmp( name, "back" ) )
attrib = charRGBA_New( &tsp->back[0] );
- ELSEIF_TSP_RGBA( back )
ELSEIF_TSP_RGBA( text )
ELSEIF_TSP_RGBA( text_hi )
ELSEIF_TSP_RGBA( header )
@@ -222,6 +228,11 @@ static int ThemeSpace_setAttr( BPy_ThemeSpace * self, char *name,
ELSEIF_TSP_RGBA( face_select )
ELSEIF_TSP_RGBA( face_dot )
ELSEIF_TSP_RGBA( normal )
+ ELSEIF_TSP_RGBA( syntaxl )
+ ELSEIF_TSP_RGBA( syntaxn )
+ ELSEIF_TSP_RGBA( syntaxb )
+ ELSEIF_TSP_RGBA( syntaxv )
+ ELSEIF_TSP_RGBA( syntaxc )
else if( !strcmp( name, "vertex_size" ) ) {
int val;
diff --git a/source/blender/src/drawscript.c b/source/blender/src/drawscript.c
index c4ec1a4db3a..30c3e11f00b 100644
--- a/source/blender/src/drawscript.c
+++ b/source/blender/src/drawscript.c
@@ -85,13 +85,14 @@ void winqreadscriptspace(struct ScrArea *sa, void *spacedata, struct BWinEvent *
void drawscriptspace(ScrArea *sa, void *spacedata)
{
SpaceScript *sc = curarea->spacedata.first;
+ Script *script = NULL;
glClearColor(0.6, 0.6, 0.6, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
myortho2(-0.5, curarea->winrct.xmax-curarea->winrct.xmin-0.5, -0.5, curarea->winrct.ymax-curarea->winrct.ymin-0.5);
if (!sc->script) {
- Script *script = G.main->script.first;
+ script = G.main->script.first;
while (script) {
@@ -105,7 +106,16 @@ void drawscriptspace(ScrArea *sa, void *spacedata)
if (!sc->script) return;
- BPY_spacescript_do_pywin_draw(sc);
+ script = sc->script;
+
+ if (script->py_draw) {
+ BPY_spacescript_do_pywin_draw(sc);
+ }
+ /* quick hack for 2.37a for scripts that call the progress bar inside a
+ * file selector callback, to show previous space after finishing, w/o
+ * needing an event */
+ else if (!script->flags && !script->py_event && !script->py_button)
+ addqueue(curarea->win, MOUSEX, 0);
}
void winqreadscriptspace(struct ScrArea *sa, void *spacedata, struct BWinEvent *evt)
@@ -117,7 +127,15 @@ void winqreadscriptspace(struct ScrArea *sa, void *spacedata, struct BWinEvent *
Script *script = sc->script;
if (script) {
- BPY_spacescript_do_pywin_event(sc, event, val, ascii);
+ if (script->py_event || script->py_button)
+ BPY_spacescript_do_pywin_event(sc, event, val, ascii);
+
+ /* for file/image sel scripts: if user leaves file/image selection space,
+ * this frees the script (since it can't be accessed anymore): */
+ else if (script->flags == SCRIPT_FILESEL) {
+ script->flags = 0;
+ script->lastspace = SPACE_SCRIPT;
+ }
if (!script->flags) {/* finished with this script, let's free it */
if (script->lastspace != SPACE_SCRIPT)