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
path: root/source
diff options
context:
space:
mode:
authorWillian Padovani Germano <wpgermano@gmail.com>2004-11-02 08:13:52 +0300
committerWillian Padovani Germano <wpgermano@gmail.com>2004-11-02 08:13:52 +0300
commit073715333881762b459f9d41547e8b6e10f07fea (patch)
tree55a33006875bdf557be66c1e8624074dde7ccc1d /source
parentbad7e33eacdc33e63407185be2c120331bbee8d0 (diff)
BPython:
-- applied patch by Michael Reimpell that lets scripts registration info be either commented out or not (commented, it doesn't interfere with Python documentation tools. The patch also fixes potential overflows, thanks (and sorry for the confusion) again, Michael. -- fixed NMesh_hasFaceUV, it was returning true for false and vice-versa. Reported by Jonas Petersen with patch, thanks. -- added 'homedir' and 'uscriptsdir' to Blender.Get() to get Blender's home dir and the user defined scripts dir. -- related to the above doc updates.
Diffstat (limited to 'source')
-rw-r--r--source/blender/python/BPY_menus.c341
-rw-r--r--source/blender/python/api2_2x/Blender.c15
-rw-r--r--source/blender/python/api2_2x/NMesh.c4
-rw-r--r--source/blender/python/api2_2x/doc/Blender.py6
-rw-r--r--source/blender/python/api2_2x/doc/Window.py24
5 files changed, 224 insertions, 166 deletions
diff --git a/source/blender/python/BPY_menus.c b/source/blender/python/BPY_menus.c
index 5a2db4d1be2..6bae8fdf3e0 100644
--- a/source/blender/python/BPY_menus.c
+++ b/source/blender/python/BPY_menus.c
@@ -25,7 +25,7 @@
*
* This is a new part of Blender.
*
- * Contributor(s): Willian P. Germano
+ * Contributor(s): Willian P. Germano, Michael Reimpell
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
@@ -583,171 +583,198 @@ void BPyMenu_PrintAllEntries( void )
}
}
-/* bpymenu_GetDataFromDir:
- * this function scans the scripts dir looking for .py files with the
+/** Creates BPyMenu entries for scripts from directory.
+ *
+ * This function scans the scripts directory looking for .py files with the
* right header and menu info, using that to fill the bpymenu structs.
* whichdir defines if the script is in the default scripts dir or the
* user defined one (U.pythondir: whichdir == 1).
* Speed is important.
-*/
+ * <code>whichdir</code> defines if the script is in the default scripts dir
+ * or the user defined one (U.pythondir: <code>whichdir == 1</code>).
+ * <p>
+ * The first line of the script must be '<code>#!BPY</code>'.
+ * The header registration lines must appear between the first pair of
+ * '<code># \"\"\"</code>' and follow this order (the single-quotes are part of
+ * the format):
+ * <p>
+ * <code>
+ * # \"\"\"<br>
+ * # Name: 'script name for the menu'<br>
+ * # Blender: <code>short int</code> (minimal Blender version)<br>
+ * # Group: 'group name' (defines menu)<br>
+ * # Submenu: 'submenu name' related_1word_arg<br>
+ * # Tooltip: 'tooltip for the menu'<br>
+ * # \"\"\"<br>
+ * </code>
+ * <p>
+ * Notes:
+ * <ul>
+ * <li> There may be more than one submenu line, or none:
+ * Submenus and the tooltip are optional;
+ * <li> The Blender version is the same number reported by
+ * <code>Blender.Get('version')</code> in BPython or <code>G.version</code>
+ * in C;
+ * <li> Line length must be less than 99.
+ * <li> Script headers as python documentation strings without the leading
+ * hash character (#) should no longer be used.
+ * </ul>
+ *
+ * @param dirname Directory name to scan.
+ * @param whichdir Specifies the directory. 1 if user defined script directory,
+ * else default script directory.
+ * @return 0 on success.
+ */
+
static int bpymenu_CreateFromDir( char *dirname, int whichdir )
{
- DIR *dir;
- FILE *fp;
- struct stat st;
- struct dirent *dir_entry;
- BPyMenu *pymenu;
- char *s, *fname, pathstr[FILE_MAXFILE + FILE_MAXDIR];
- char line[100], w[100];
- char name[100], submenu[100], subarg[100], tooltip[100];
- int res = 0, version = 0;
-
- dir = opendir( dirname );
-
- if( !dir ) {
- if ( DEBUG )
- printf("BPyMenus warning: could not open dir %s.\n", dirname);
- return -1;
- }
-
-/* we scan the dir for filenames ending with .py and starting with the
- * right 'magic number': '#!BPY'. All others are ignored. */
-
- while( ( dir_entry = readdir( dir ) ) != NULL ) {
- fname = dir_entry->d_name;
- /* ignore anything starting with a dot */
- if( fname[0] == '.' )
- continue; /* like . and .. */
-
- /* also skip filenames whose extension isn't '.py' */
- s = strstr( fname, ".py" );
- if( !s || *( s + 3 ) != '\0' )
- continue;
-
- BLI_make_file_string( "/", pathstr, dirname, fname );
-
- /* paranoia: check if this is really a file and not a disguised dir */
- if( ( stat( pathstr, &st ) == -1 ) || !S_ISREG( st.st_mode ) )
- continue;
-
- fp = fopen( pathstr, "rb" );
-
- if( !fp ) {
- if( DEBUG )
- printf( "BPyMenus error: couldn't open %s.\n",
- pathstr );
- continue;
- }
-
- /* finally, look for the start string '#!BPY', with
- * or w/o white space(s) between #! and BPY */
- fgets( line, 100, fp );
- if( line[0] != '#' || line[1] != '!' )
- goto discard;
-
- if( !strstr( line, "BPY" ) )
- goto discard;
-
- /* file passed the tests, look for the three double-quotes */
- while( fgets( line, 100, fp ) ) {
- if( strstr( line, "\"\"\"" )) {
- res = 1; /* found */
- break;
+ DIR *dir; /* directory stream object */
+ FILE *currentFile; /* file stream object */
+ struct dirent *dirEntry; /* directory entry */
+ struct stat fileStatus;
+ char *fileExtension;
+ char fileName[FILE_MAXFILE + FILE_MAXDIR]; /* filename including path */
+ /* parser variables */
+ char line[100];
+ char head[100];
+ char middle[100];
+ char tail[100];
+ int nMatches;
+ int parserState;
+ /* script header variables */
+ char scriptName[100];
+ int scriptBlender;
+ int scriptGroup;
+ BPyMenu *scriptMenu = NULL;
+ /* other */
+ int scanDir = 1;
+ int returnValue = 0;
+
+ /* open directory stream */
+ dir = opendir(dirname);
+ if (dir != NULL) {
+ /* directory stream opened */
+ while (((dirEntry = readdir(dir)) != NULL) && (scanDir == 1)) {
+ /* Check if filename does not start with a dot,
+ * ends with '.py' and is a regular file. */
+ BLI_make_file_string("/", fileName, dirname, dirEntry->d_name);
+ fileExtension = strstr(dirEntry->d_name, ".py");
+
+ if ((strncmp(dirEntry->d_name, ".", 1) != 0)
+ && (fileExtension != NULL)
+ && (*(fileExtension + 3) == '\0')
+ && (stat(fileName, &fileStatus) == 0)
+ && (S_ISREG(fileStatus.st_mode))) {
+ /* check file header */
+ currentFile = fopen(fileName, "rb");
+ if (currentFile != NULL) {
+ parserState = 1; /* state of parser, 0 to terminate */
+ while ((parserState != 0) && (fgets(line, 100, currentFile) != NULL)) {
+ switch (parserState) {
+ case 1: /* #!BPY */
+ if (strncmp(line, "#!BPY", 5) == 0) {
+ parserState++;
+ } else {
+ parserState = 0;
+ }
+ break;
+ case 2: /* # \"\"\" */
+ if ((strstr(line, "\"\"\""))) {
+ parserState++;
+ }
+ break;
+ case 3: /* # Name: 'script name for the menu' */
+ nMatches = sscanf(line, "%[^']'%[^']'%c", head, scriptName, tail);
+ if ((nMatches == 3) && (strstr(head, "Name:") != NULL)) {
+ parserState++;
+ } else {
+ if (DEBUG) {
+ fprintf(stderr, "BPyMenus error: Wrong 'Name' line: %s\n", fileName);
+ }
+ parserState = 0;
+ }
+ break;
+ case 4: /* # Blender: <short int> */
+ nMatches = sscanf(line, "%[^1234567890]%i%c", head, &scriptBlender, tail);
+ if (nMatches == 3) {
+ parserState++;
+ } else {
+ if (DEBUG) {
+ fprintf(stderr, "BPyMenus error: Wrong 'Blender' line: %s\n", fileName);
+ }
+ parserState = 0;
+ }
+ break;
+ case 5: /* # Group: 'group name' */
+ nMatches = sscanf(line, "%[^']'%[^']'%c", head, middle, tail);
+ if ((nMatches == 3) && (strstr(head, "Group:") != NULL)) {
+ scriptGroup = bpymenu_group_atoi(middle);
+ if (scriptGroup < 0) {
+ if (DEBUG) {
+ fprintf(stderr, "BPyMenus error: Unknown group \"%s\": %s\n", middle, fileName);
+ }
+ parserState = 0;
+ } else {
+ /* register script */
+ scriptMenu = bpymenu_AddEntry(scriptGroup, (short int) scriptBlender, scriptName,
+ dirEntry->d_name, whichdir, NULL);
+ if (scriptMenu == NULL) {
+ if (DEBUG) {
+ fprintf(stderr, "BPyMenus error: Couldn't create entry for: %s\n", fileName);
+ }
+ /* abort */
+ parserState = 0;
+ scanDir = 0;
+ returnValue = -2;
+ } else {
+ parserState++;
+ }
+ }
+ } else {
+ if (DEBUG) {
+ fprintf(stderr, "BPyMenus error: Wrong 'Group' line: %s\n", fileName);
+ }
+ parserState = 0;
+ }
+ break;
+ case 6: /* optional elements */
+ /* # Submenu: 'submenu name' related_1word_arg */
+ nMatches = sscanf(line, "%[^']'%[^']'%s\n", head, middle, tail);
+ if ((nMatches == 3) && (strstr(head, "Submenu:") != NULL)) {
+ bpymenu_AddSubEntry(scriptMenu, middle, tail);
+ } else {
+ /* # Tooltip: 'tooltip for the menu */
+ nMatches = sscanf(line, "%[^']'%[^']'%c", head, middle, tail);
+ if ((nMatches == 3)
+ && ((strstr(head, "Tooltip:") != NULL) || (strstr(head, "Tip:") != NULL))) {
+ bpymenu_set_tooltip(scriptMenu, middle);
+ }
+ parserState = 0;
+ }
+ break;
+ default:
+ parserState = 0;
+ break;
+ }
+ }
+ /* close file stream */
+ fclose(currentFile);
+ } else {
+ /* open file failed */
+ if(DEBUG) {
+ fprintf(stderr, "BPyMenus error: Couldn't open %s.\n", dirEntry->d_name);
+ }
+ }
}
}
-
- if( !res )
- goto discard;
-
- /* Now we're ready to get the registration info. A little more structure
- * was imposed to the format, for speed. The registration lines must
- * appear between the first pair of triple double-quotes and
- * follow this order (the single-quotes are part of the format,
- * but as noted below, now the whole registration part can be commented
- * out so external Python tools can ignore them):
- *
- * Name: 'script name for the menu'
- * Blender: <short int> (minimal Blender version)
- * Group: 'group name' (defines menu)
- * Submenu: 'submenu name' related_1word_arg
- * Tooltip: 'tooltip for the menu'
- *
- * notes:
- * - there may be more than one submenu line, or none:
- * submenus and the tooltip are optional;
- * - the Blender version is the same number reported by
- * Blender.Get('version') in BPython or G.version in C;
- * - NEW in 2.35: Michael Reimpell suggested and even provided
- * a patch (read but not used to keep changes to a minimum for
- * now, shame on me) to make registration code also accept
- * commented out registration lines, so that BPython menu
- * registration doesn't mess with Python documentation tools. */
-
- /* first the name: */
- res = fscanf( fp, "%[^']'%[^'\r\n]'\n", w, name );
- if( ( res != 2 ) || !strstr(w, "Name") ) {
- if( DEBUG )
- printf( "BPyMenus error: wrong 'Name' line in %s.\n", pathstr );
- goto discard;
- }
-
- /* minimal Blender version: */
- res = fscanf( fp, "%s %d\n", w, &version );
- if( ( res != 2 ) || !strstr(w, "Blender") ) {
- if( DEBUG )
- printf( "BPyMenus error: wrong 'Blender' line in %s.\n", pathstr );
- goto discard;
- }
-
- line[0] = '\0'; /* used as group for this part */
-
- /* the group: */
- res = fscanf( fp, "%[^']'%[^'\r\n]'\n", w, line );
- if( ( res != 2 ) || !strstr(w, "Group" ) ) {
- if( DEBUG )
- printf( "BPyMenus error: wrong 'Group' line in %s.\n", pathstr );
- goto discard;
- }
-
- res = bpymenu_group_atoi( line );
- if( res < 0 ) {
- if( DEBUG )
- printf( "BPyMenus error: unknown 'Group' %s in %s.\n", line, pathstr );
- goto discard;
- }
-
- pymenu = bpymenu_AddEntry( res, ( short ) version, name, fname,
- whichdir, NULL );
- if( !pymenu ) {
- if( DEBUG )
- printf( "BPyMenus error: couldn't create entry for %s.\n", pathstr );
- fclose( fp );
- closedir( dir );
- return -2;
- }
-
- /* the (optional) submenu(s): */
- while( fgets( line, 100, fp ) ) {
- res = sscanf( line, "%[^']'%[^'\r\n]'%s\n", w, submenu,
- subarg );
- if( ( res != 3 ) || !strstr( w, "Submenu" ) )
- break;
- bpymenu_AddSubEntry( pymenu, submenu, subarg );
- }
-
- /* the (optional) tooltip: */
- res = sscanf( line, "%[^']'%[^'\r\n]'\n", w, tooltip );
- if( ( res == 2 ) && (!strstr( w, "Tooltip") || !strstr( w, "Tip" ))) {
- bpymenu_set_tooltip( pymenu, tooltip );
- }
-
- discard:
- fclose( fp );
- continue;
+ /* close directory stream */
+ closedir(dir);
+ } else {
+ /* open directory stream failed */
+ fprintf(stderr, "opendir %s failed: %s\n", dirname, strerror(errno));
+ returnValue = -1;
}
-
- closedir( dir );
- return 0;
+ return returnValue;
}
static int bpymenu_GetStatMTime( char *name, int is_file, time_t * mtime )
diff --git a/source/blender/python/api2_2x/Blender.c b/source/blender/python/api2_2x/Blender.c
index d9b4151388d..761fffabb50 100644
--- a/source/blender/python/api2_2x/Blender.c
+++ b/source/blender/python/api2_2x/Blender.c
@@ -97,8 +97,10 @@ static char Blender_Get_doc[] = "(request) - Retrieve settings from Blender\n\
'staframe' - Returns the start frame of the animation\n\
'endframe' - Returns the end frame of the animation\n\
'filename' - Returns the name of the last file read or written\n\
+ 'homedir' - Returns Blender's home dir\n\
'datadir' - Returns the dir where scripts can save their data, if available\n\
'scriptsdir' - Returns the main dir where scripts are kept, if available\n\
+ 'uscriptsdir' - Returns the user defined dir for scripts, if available\n\
'version' - Returns the Blender version number";
static char Blender_Redraw_doc[] = "() - Redraw all 3D windows";
@@ -217,6 +219,13 @@ static PyObject *Blender_Get( PyObject * self, PyObject * args )
if( StringEqual( str, "filename" ) ) {
return ( PyString_FromString( G.sce ) );
}
+ if( StringEqual( str, "homedir" ) ) {
+ if( BLI_exists( bpy_gethome() ))
+ return PyString_FromString( bpy_gethome() );
+ else
+ return EXPP_incr_ret( Py_None );
+ }
+
if( StringEqual( str, "datadir" ) ) {
char datadir[FILE_MAXDIR];
BLI_make_file_string( "/", datadir, bpy_gethome( ),
@@ -235,6 +244,12 @@ static PyObject *Blender_Get( PyObject * self, PyObject * args )
else
return EXPP_incr_ret( Py_None );
}
+ if( StringEqual( str, "uscriptsdir" ) ) {
+ if( BLI_exists( U.pythondir ) )
+ return PyString_FromString( U.pythondir );
+ else
+ return EXPP_incr_ret( Py_None );
+ }
/* According to the old file (opy_blender.c), the following if
statement is a quick hack and needs some clean up. */
if( StringEqual( str, "vrmloptions" ) ) {
diff --git a/source/blender/python/api2_2x/NMesh.c b/source/blender/python/api2_2x/NMesh.c
index 53bceb23cd8..38d189e007f 100644
--- a/source/blender/python/api2_2x/NMesh.c
+++ b/source/blender/python/api2_2x/NMesh.c
@@ -1059,10 +1059,10 @@ static PyObject *NMesh_hasFaceUV( PyObject * self, PyObject * args )
switch ( flag ) {
case 0:
- me->flags |= NMESH_HASFACEUV;
+ me->flags &= ~NMESH_HASFACEUV;
break;
case 1:
- me->flags &= ~NMESH_HASFACEUV;
+ me->flags |= NMESH_HASFACEUV;
break;
default:
break;
diff --git a/source/blender/python/api2_2x/doc/Blender.py b/source/blender/python/api2_2x/doc/Blender.py
index c6bb41a3d6d..a864566c4e5 100644
--- a/source/blender/python/api2_2x/doc/Blender.py
+++ b/source/blender/python/api2_2x/doc/Blender.py
@@ -10,7 +10,7 @@
"""
The main Blender module.
-B{New}: 'scriptsdir' parameter in L{Get}.
+B{New}: 'homedir', 'scriptsdir' and 'uscriptsdir' parameters in L{Get}.
Blender
=======
@@ -36,11 +36,15 @@ def Get (request):
- 'staframe': the start frame of the animation
- 'endframe': the end frame of the animation
- 'filename': the name of the last file read or written
+ - 'homedir': Blender's home dir
- 'datadir' : the path to the dir where scripts should store and
retrieve their data files, including saved configuration (can
be None, if not found).
- 'scriptsdir': the path to the main dir where scripts are stored
(can be None, if not found).
+ - 'uscriptsdir': the path to the user defined dir for scripts, see
+ the paths tab in the User Preferences window in Blender
+ (can be None, if not found).
- 'version' : the Blender version number
@return: The requested data.
"""
diff --git a/source/blender/python/api2_2x/doc/Window.py b/source/blender/python/api2_2x/doc/Window.py
index 60f1396dbce..bde72cc815c 100644
--- a/source/blender/python/api2_2x/doc/Window.py
+++ b/source/blender/python/api2_2x/doc/Window.py
@@ -87,6 +87,13 @@ DrawProgressBar::
- L: left mouse button
- M: middle mouse button
- R: right mouse button
+
+@warn: The event system in Blender needs a rewrite, though we don't know when that will happen. Until then, event related functions here (L{QAdd}, L{QRead},
+L{QHandle}, etc.) can be used, but they are actually experimental and can be
+substituted for a better method when the rewrite happens. In other words, use
+them at your own risk, because though they should work well and allow many
+interesting and powerful possibilities, they can be deprecated in some future
+version of Blender / Blender Python.
"""
def Redraw (spacetype = '<Types.VIEW3D>'):
@@ -305,18 +312,23 @@ def QRead ():
# let's catch all events and move the 3D Cursor when user presses
# the left mouse button.
from Blender import Draw, Window
+
+ v3d = Window.ScreenInfo(Window.Types.VIEW3D)
+ id = v3d[0]['id'] # get the (first) VIEW3D's id
+
done = 0
+
while not done: # enter a 'get event' loop
evt, val = Window.QRead() # catch next event
- if evt in [Draw.ESCKEY, Draw.QKEY]: done = 1 # end loop
+ if evt in [Draw.MOUSEX, Draw.MOUSEY]:
+ continue # speeds things up, ignores mouse movement
+ elif evt in [Draw.ESCKEY, Draw.QKEY]: done = 1 # end loop
elif evt == Draw.SPACEKEY:
Draw.PupMenu("Hey!|What did you expect?")
elif evt == Draw.Redraw: # catch redraw events to handle them
Window.RedrawAll() # redraw all areas
- elif evt == Draw.LEFTMOUSE and val: # left button pressed
- v3d = Window.ScreenInfo(Window.Types.VIEW3D)
- id = v3d[0]['id'] # get the (first) VIEW3D's id
- Window.QAdd(id, evt, 1) # add the caught mouse event to it
+ elif evt == Draw.LEFTMOUSE: # left button pressed
+ Window.QAdd(id, evt, 1) # add the caught mouse event to our v3d
# actually we should check if the event happened inside that area,
# using Window.GetMouseCoords() and v3d[0]['vertices'] values.
Window.QHandle(id) # process the event
@@ -328,7 +340,7 @@ def QRead ():
@return: [event, val], where:
- event: int - the key or mouse event (see L{Draw});
- val: int - 1 for a key press, 0 for a release, new x or y coordinates
- for mouse events.
+ for mouse movement events.
"""
def QAdd (win, event, val, after = 0):