-- 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.
This commit is contained in:
2004-11-02 05:13:52 +00:00
parent bad7e33eac
commit 0737153338
5 changed files with 224 additions and 166 deletions

View File

@@ -25,7 +25,7 @@
* *
* This is a new part of Blender. * 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 ***** * ***** END GPL/BL DUAL LICENSE BLOCK *****
*/ */
@@ -583,171 +583,198 @@ void BPyMenu_PrintAllEntries( void )
} }
} }
/* bpymenu_GetDataFromDir: /** Creates BPyMenu entries for scripts from directory.
* this function scans the scripts dir looking for .py files with the *
* This function scans the scripts directory looking for .py files with the
* right header and menu info, using that to fill the bpymenu structs. * 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 * whichdir defines if the script is in the default scripts dir or the
* user defined one (U.pythondir: whichdir == 1). * user defined one (U.pythondir: whichdir == 1).
* Speed is important. * 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 ) static int bpymenu_CreateFromDir( char *dirname, int whichdir )
{ {
DIR *dir; DIR *dir; /* directory stream object */
FILE *fp; FILE *currentFile; /* file stream object */
struct stat st; struct dirent *dirEntry; /* directory entry */
struct dirent *dir_entry; struct stat fileStatus;
BPyMenu *pymenu; char *fileExtension;
char *s, *fname, pathstr[FILE_MAXFILE + FILE_MAXDIR]; char fileName[FILE_MAXFILE + FILE_MAXDIR]; /* filename including path */
char line[100], w[100]; /* parser variables */
char name[100], submenu[100], subarg[100], tooltip[100]; char line[100];
int res = 0, version = 0; char head[100];
char middle[100];
dir = opendir( dirname ); char tail[100];
int nMatches;
if( !dir ) { int parserState;
if ( DEBUG ) /* script header variables */
printf("BPyMenus warning: could not open dir %s.\n", dirname); char scriptName[100];
return -1; int scriptBlender;
} int scriptGroup;
BPyMenu *scriptMenu = NULL;
/* we scan the dir for filenames ending with .py and starting with the /* other */
* right 'magic number': '#!BPY'. All others are ignored. */ int scanDir = 1;
int returnValue = 0;
while( ( dir_entry = readdir( dir ) ) != NULL ) {
fname = dir_entry->d_name; /* open directory stream */
/* ignore anything starting with a dot */ dir = opendir(dirname);
if( fname[0] == '.' ) if (dir != NULL) {
continue; /* like . and .. */ /* directory stream opened */
while (((dirEntry = readdir(dir)) != NULL) && (scanDir == 1)) {
/* also skip filenames whose extension isn't '.py' */ /* Check if filename does not start with a dot,
s = strstr( fname, ".py" ); * ends with '.py' and is a regular file. */
if( !s || *( s + 3 ) != '\0' ) BLI_make_file_string("/", fileName, dirname, dirEntry->d_name);
continue; fileExtension = strstr(dirEntry->d_name, ".py");
BLI_make_file_string( "/", pathstr, dirname, fname ); if ((strncmp(dirEntry->d_name, ".", 1) != 0)
&& (fileExtension != NULL)
/* paranoia: check if this is really a file and not a disguised dir */ && (*(fileExtension + 3) == '\0')
if( ( stat( pathstr, &st ) == -1 ) || !S_ISREG( st.st_mode ) ) && (stat(fileName, &fileStatus) == 0)
continue; && (S_ISREG(fileStatus.st_mode))) {
/* check file header */
fp = fopen( pathstr, "rb" ); currentFile = fopen(fileName, "rb");
if (currentFile != NULL) {
if( !fp ) { parserState = 1; /* state of parser, 0 to terminate */
if( DEBUG ) while ((parserState != 0) && (fgets(line, 100, currentFile) != NULL)) {
printf( "BPyMenus error: couldn't open %s.\n", switch (parserState) {
pathstr ); case 1: /* #!BPY */
continue; if (strncmp(line, "#!BPY", 5) == 0) {
} parserState++;
} else {
/* finally, look for the start string '#!BPY', with parserState = 0;
* or w/o white space(s) between #! and BPY */ }
fgets( line, 100, fp ); break;
if( line[0] != '#' || line[1] != '!' ) case 2: /* # \"\"\" */
goto discard; if ((strstr(line, "\"\"\""))) {
parserState++;
if( !strstr( line, "BPY" ) ) }
goto discard; break;
case 3: /* # Name: 'script name for the menu' */
/* file passed the tests, look for the three double-quotes */ nMatches = sscanf(line, "%[^']'%[^']'%c", head, scriptName, tail);
while( fgets( line, 100, fp ) ) { if ((nMatches == 3) && (strstr(head, "Name:") != NULL)) {
if( strstr( line, "\"\"\"" )) { parserState++;
res = 1; /* found */ } else {
break; 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);
}
}
} }
} }
/* close directory stream */
if( !res ) closedir(dir);
goto discard; } else {
/* open directory stream failed */
/* Now we're ready to get the registration info. A little more structure fprintf(stderr, "opendir %s failed: %s\n", dirname, strerror(errno));
* was imposed to the format, for speed. The registration lines must returnValue = -1;
* 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;
} }
return returnValue;
closedir( dir );
return 0;
} }
static int bpymenu_GetStatMTime( char *name, int is_file, time_t * mtime ) static int bpymenu_GetStatMTime( char *name, int is_file, time_t * mtime )

View File

@@ -97,8 +97,10 @@ static char Blender_Get_doc[] = "(request) - Retrieve settings from Blender\n\
'staframe' - Returns the start frame of the animation\n\ 'staframe' - Returns the start frame of the animation\n\
'endframe' - Returns the end 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\ '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\ '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\ '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"; 'version' - Returns the Blender version number";
static char Blender_Redraw_doc[] = "() - Redraw all 3D windows"; 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" ) ) { if( StringEqual( str, "filename" ) ) {
return ( PyString_FromString( G.sce ) ); 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" ) ) { if( StringEqual( str, "datadir" ) ) {
char datadir[FILE_MAXDIR]; char datadir[FILE_MAXDIR];
BLI_make_file_string( "/", datadir, bpy_gethome( ), BLI_make_file_string( "/", datadir, bpy_gethome( ),
@@ -235,6 +244,12 @@ static PyObject *Blender_Get( PyObject * self, PyObject * args )
else else
return EXPP_incr_ret( Py_None ); 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 /* According to the old file (opy_blender.c), the following if
statement is a quick hack and needs some clean up. */ statement is a quick hack and needs some clean up. */
if( StringEqual( str, "vrmloptions" ) ) { if( StringEqual( str, "vrmloptions" ) ) {

View File

@@ -1059,10 +1059,10 @@ static PyObject *NMesh_hasFaceUV( PyObject * self, PyObject * args )
switch ( flag ) { switch ( flag ) {
case 0: case 0:
me->flags |= NMESH_HASFACEUV; me->flags &= ~NMESH_HASFACEUV;
break; break;
case 1: case 1:
me->flags &= ~NMESH_HASFACEUV; me->flags |= NMESH_HASFACEUV;
break; break;
default: default:
break; break;

View File

@@ -10,7 +10,7 @@
""" """
The main Blender module. The main Blender module.
B{New}: 'scriptsdir' parameter in L{Get}. B{New}: 'homedir', 'scriptsdir' and 'uscriptsdir' parameters in L{Get}.
Blender Blender
======= =======
@@ -36,11 +36,15 @@ def Get (request):
- 'staframe': the start frame of the animation - 'staframe': the start frame of the animation
- 'endframe': the end frame of the animation - 'endframe': the end frame of the animation
- 'filename': the name of the last file read or written - '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 - 'datadir' : the path to the dir where scripts should store and
retrieve their data files, including saved configuration (can retrieve their data files, including saved configuration (can
be None, if not found). be None, if not found).
- 'scriptsdir': the path to the main dir where scripts are stored - 'scriptsdir': the path to the main dir where scripts are stored
(can be None, if not found). (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 - 'version' : the Blender version number
@return: The requested data. @return: The requested data.
""" """

View File

@@ -87,6 +87,13 @@ DrawProgressBar::
- L: left mouse button - L: left mouse button
- M: middle mouse button - M: middle mouse button
- R: right 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>'): def Redraw (spacetype = '<Types.VIEW3D>'):
@@ -305,18 +312,23 @@ def QRead ():
# let's catch all events and move the 3D Cursor when user presses # let's catch all events and move the 3D Cursor when user presses
# the left mouse button. # the left mouse button.
from Blender import Draw, Window from Blender import Draw, Window
v3d = Window.ScreenInfo(Window.Types.VIEW3D)
id = v3d[0]['id'] # get the (first) VIEW3D's id
done = 0 done = 0
while not done: # enter a 'get event' loop while not done: # enter a 'get event' loop
evt, val = Window.QRead() # catch next event 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: elif evt == Draw.SPACEKEY:
Draw.PupMenu("Hey!|What did you expect?") Draw.PupMenu("Hey!|What did you expect?")
elif evt == Draw.Redraw: # catch redraw events to handle them elif evt == Draw.Redraw: # catch redraw events to handle them
Window.RedrawAll() # redraw all areas Window.RedrawAll() # redraw all areas
elif evt == Draw.LEFTMOUSE and val: # left button pressed elif evt == Draw.LEFTMOUSE: # left button pressed
v3d = Window.ScreenInfo(Window.Types.VIEW3D) Window.QAdd(id, evt, 1) # add the caught mouse event to our v3d
id = v3d[0]['id'] # get the (first) VIEW3D's id
Window.QAdd(id, evt, 1) # add the caught mouse event to it
# actually we should check if the event happened inside that area, # actually we should check if the event happened inside that area,
# using Window.GetMouseCoords() and v3d[0]['vertices'] values. # using Window.GetMouseCoords() and v3d[0]['vertices'] values.
Window.QHandle(id) # process the event Window.QHandle(id) # process the event
@@ -328,7 +340,7 @@ def QRead ():
@return: [event, val], where: @return: [event, val], where:
- event: int - the key or mouse event (see L{Draw}); - 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 - 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): def QAdd (win, event, val, after = 0):