compiler fix part 1
[[Split portion of a mixed commit.]]
This commit is contained in:
1118
source/blender/python/BPY_menus.c
Normal file
1118
source/blender/python/BPY_menus.c
Normal file
@@ -0,0 +1,1118 @@
|
||||
/*
|
||||
* $Id: BPY_menus.c 12932 2007-12-17 20:21:06Z theeth $
|
||||
*
|
||||
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version. The Blender
|
||||
* Foundation also sells licenses for use in proprietary software under
|
||||
* the Blender License. See http://www.blender.org/BL/ for information
|
||||
* about this.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This is a new part of Blender.
|
||||
*
|
||||
* Contributor(s): Willian P. Germano, Michael Reimpell
|
||||
*
|
||||
* ***** END GPL/BL DUAL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/*
|
||||
*This is the main file responsible for having bpython scripts accessible
|
||||
* from Blender menus. To know more, please start with its header file.
|
||||
*/
|
||||
|
||||
#include "BPY_menus.h"
|
||||
|
||||
#include <Python.h>
|
||||
#ifndef WIN32
|
||||
#include <dirent.h>
|
||||
#else
|
||||
#include "BLI_winstuff.h"
|
||||
#endif
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_utildefines.h"
|
||||
#include "BLI_blenlib.h"
|
||||
#include "MEM_guardedalloc.h"
|
||||
#include "DNA_userdef_types.h" /* for U.pythondir */
|
||||
#include "api2_2x/EXPP_interface.h" /* for bpy_gethome() */
|
||||
|
||||
#define BPYMENU_DATAFILE "Bpymenus"
|
||||
#define MAX_DIR_DEPTH 4 /* max depth for traversing scripts dirs */
|
||||
#define MAX_DIR_NUMBER 30 /* max number of dirs in scripts dirs trees */
|
||||
|
||||
static int DEBUG;
|
||||
static int Dir_Depth;
|
||||
static int Dirs_Number;
|
||||
|
||||
/* BPyMenuTable holds all registered pymenus, as linked lists for each menu
|
||||
* where they can appear (see PYMENUHOOKS enum in BPY_menus.h).
|
||||
*/
|
||||
BPyMenu *BPyMenuTable[PYMENU_TOTAL];
|
||||
|
||||
static int bpymenu_group_atoi( char *str )
|
||||
{
|
||||
if( !strcmp( str, "Export" ) )
|
||||
return PYMENU_EXPORT;
|
||||
else if( !strcmp( str, "Import" ) )
|
||||
return PYMENU_IMPORT;
|
||||
else if( !strcmp( str, "Help" ) )
|
||||
return PYMENU_HELP;
|
||||
else if( !strcmp( str, "HelpWebsites" ) )
|
||||
return PYMENU_HELPWEBSITES;
|
||||
else if( !strcmp( str, "HelpSystem" ) )
|
||||
return PYMENU_HELPSYSTEM;
|
||||
else if( !strcmp( str, "Render" ) )
|
||||
return PYMENU_RENDER;
|
||||
else if( !strcmp( str, "System" ) )
|
||||
return PYMENU_SYSTEM;
|
||||
else if( !strcmp( str, "Object" ) )
|
||||
return PYMENU_OBJECT;
|
||||
else if( !strcmp( str, "Mesh" ) )
|
||||
return PYMENU_MESH;
|
||||
else if( !strncmp( str, "Theme", 5 ) )
|
||||
return PYMENU_THEMES;
|
||||
else if( !strcmp( str, "Add" ) )
|
||||
return PYMENU_ADD;
|
||||
else if( !strcmp( str, "Wizards" ) )
|
||||
return PYMENU_WIZARDS;
|
||||
else if( !strcmp( str, "Animation" ) )
|
||||
return PYMENU_ANIMATION;
|
||||
else if( !strcmp( str, "Materials" ) )
|
||||
return PYMENU_MATERIALS;
|
||||
else if( !strcmp( str, "UV" ) )
|
||||
return PYMENU_UV;
|
||||
else if( !strcmp( str, "Image" ) )
|
||||
return PYMENU_IMAGE;
|
||||
else if( !strcmp( str, "FaceSelect" ) )
|
||||
return PYMENU_FACESELECT;
|
||||
else if( !strcmp( str, "WeightPaint" ) )
|
||||
return PYMENU_WEIGHTPAINT;
|
||||
else if( !strcmp( str, "VertexPaint" ) )
|
||||
return PYMENU_VERTEXPAINT;
|
||||
else if( !strcmp( str, "UVCalculation" ) )
|
||||
return PYMENU_UVCALCULATION;
|
||||
else if( !strcmp( str, "Armature" ) )
|
||||
return PYMENU_ARMATURE;
|
||||
else if( !strcmp( str, "ScriptTemplate" ) )
|
||||
return PYMENU_SCRIPTTEMPLATE;
|
||||
else if( !strcmp( str, "MeshFaceKey" ) )
|
||||
return PYMENU_MESHFACEKEY;
|
||||
else if( !strcmp( str, "AddMesh" ) )
|
||||
return PYMENU_ADDMESH;
|
||||
/* "Misc" or an inexistent group name: use misc */
|
||||
else
|
||||
return PYMENU_MISC;
|
||||
}
|
||||
|
||||
char *BPyMenu_group_itoa( short menugroup )
|
||||
{
|
||||
switch ( menugroup ) {
|
||||
case PYMENU_EXPORT:
|
||||
return "Export";
|
||||
break;
|
||||
case PYMENU_IMPORT:
|
||||
return "Import";
|
||||
break;
|
||||
case PYMENU_ADD:
|
||||
return "Add";
|
||||
break;
|
||||
case PYMENU_HELP:
|
||||
return "Help";
|
||||
break;
|
||||
case PYMENU_HELPWEBSITES:
|
||||
return "HelpWebsites";
|
||||
break;
|
||||
case PYMENU_HELPSYSTEM:
|
||||
return "HelpSystem";
|
||||
break;
|
||||
case PYMENU_RENDER:
|
||||
return "Render";
|
||||
break;
|
||||
case PYMENU_SYSTEM:
|
||||
return "System";
|
||||
break;
|
||||
case PYMENU_OBJECT:
|
||||
return "Object";
|
||||
break;
|
||||
case PYMENU_MESH:
|
||||
return "Mesh";
|
||||
break;
|
||||
case PYMENU_THEMES:
|
||||
return "Themes";
|
||||
break;
|
||||
case PYMENU_WIZARDS:
|
||||
return "Wizards";
|
||||
break;
|
||||
case PYMENU_ANIMATION:
|
||||
return "Animation";
|
||||
break;
|
||||
case PYMENU_MATERIALS:
|
||||
return "Materials";
|
||||
break;
|
||||
case PYMENU_UV:
|
||||
return "UV";
|
||||
break;
|
||||
case PYMENU_IMAGE:
|
||||
return "Image";
|
||||
break;
|
||||
case PYMENU_FACESELECT:
|
||||
return "FaceSelect";
|
||||
break;
|
||||
case PYMENU_WEIGHTPAINT:
|
||||
return "WeightPaint";
|
||||
break;
|
||||
case PYMENU_VERTEXPAINT:
|
||||
return "VertexPaint";
|
||||
break;
|
||||
case PYMENU_UVCALCULATION:
|
||||
return "UVCalculation";
|
||||
break;
|
||||
case PYMENU_ARMATURE:
|
||||
return "Armature";
|
||||
break;
|
||||
case PYMENU_SCRIPTTEMPLATE:
|
||||
return "ScriptTemplate";
|
||||
break;
|
||||
case PYMENU_MESHFACEKEY:
|
||||
return "MeshFaceKey";
|
||||
break;
|
||||
case PYMENU_ADDMESH:
|
||||
return "AddMesh";
|
||||
break;
|
||||
case PYMENU_MISC:
|
||||
return "Misc";
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* BPyMenu_CreatePupmenuStr:
|
||||
* build and return a meaninful string to be used by pupmenu(). The
|
||||
* string is made of a bpymenu name as title and its submenus as possible
|
||||
* choices for the user.
|
||||
*/
|
||||
char *BPyMenu_CreatePupmenuStr( BPyMenu * pym, short menugroup )
|
||||
{
|
||||
BPySubMenu *pysm = pym->submenus;
|
||||
char str[1024], str2[100];
|
||||
int i = 0, rlen;
|
||||
|
||||
if( !pym || !pysm )
|
||||
return NULL;
|
||||
|
||||
str[0] = '\0';
|
||||
|
||||
PyOS_snprintf( str2, sizeof( str2 ), "%s: %s%%t",
|
||||
BPyMenu_group_itoa( menugroup ), pym->name );
|
||||
strcat( str, str2 );
|
||||
|
||||
while( pysm ) {
|
||||
PyOS_snprintf( str2, sizeof( str2 ), "|%s%%x%d", pysm->name,
|
||||
i );
|
||||
rlen = sizeof( str ) - strlen( str );
|
||||
strncat( str, str2, rlen );
|
||||
i++;
|
||||
pysm = pysm->next;
|
||||
}
|
||||
|
||||
return BLI_strdup( str );
|
||||
}
|
||||
|
||||
static void bpymenu_RemoveAllSubEntries( BPySubMenu * smenu )
|
||||
{
|
||||
BPySubMenu *tmp;
|
||||
|
||||
while( smenu ) {
|
||||
tmp = smenu->next;
|
||||
if( smenu->name )
|
||||
MEM_freeN( smenu->name );
|
||||
if( smenu->arg )
|
||||
MEM_freeN( smenu->arg );
|
||||
MEM_freeN( smenu );
|
||||
smenu = tmp;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void BPyMenu_RemoveAllEntries( void )
|
||||
{
|
||||
BPyMenu *tmp, *pymenu;
|
||||
int i;
|
||||
|
||||
for( i = 0; i < PYMENU_TOTAL; i++ ) {
|
||||
pymenu = BPyMenuTable[i];
|
||||
while( pymenu ) {
|
||||
tmp = pymenu->next;
|
||||
if( pymenu->name )
|
||||
MEM_freeN( pymenu->name );
|
||||
if( pymenu->filename )
|
||||
MEM_freeN( pymenu->filename );
|
||||
if( pymenu->tooltip )
|
||||
MEM_freeN( pymenu->tooltip );
|
||||
if( pymenu->submenus )
|
||||
bpymenu_RemoveAllSubEntries( pymenu->
|
||||
submenus );
|
||||
MEM_freeN( pymenu );
|
||||
pymenu = tmp;
|
||||
}
|
||||
BPyMenuTable[i] = NULL;
|
||||
}
|
||||
|
||||
Dirs_Number = 0;
|
||||
Dir_Depth = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static BPyMenu *bpymenu_FindEntry( short group, char *name )
|
||||
{
|
||||
BPyMenu *pymenu;
|
||||
|
||||
if( ( group < 0 ) || ( group >= PYMENU_TOTAL ) )
|
||||
return NULL;
|
||||
|
||||
pymenu = BPyMenuTable[group];
|
||||
|
||||
while( pymenu ) {
|
||||
if( !strcmp( pymenu->name, name ) )
|
||||
return pymenu;
|
||||
pymenu = pymenu->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* BPyMenu_GetEntry:
|
||||
* given a group and a position, return the entry in that position from
|
||||
* that group.
|
||||
*/
|
||||
BPyMenu *BPyMenu_GetEntry( short group, short pos )
|
||||
{
|
||||
BPyMenu *pym = NULL;
|
||||
|
||||
if( ( group < 0 ) || ( group >= PYMENU_TOTAL ) )
|
||||
return NULL;
|
||||
|
||||
pym = BPyMenuTable[group];
|
||||
|
||||
while( pos-- ) {
|
||||
if( pym )
|
||||
pym = pym->next;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return pym; /* found entry or NULL */
|
||||
}
|
||||
|
||||
static void bpymenu_set_tooltip( BPyMenu * pymenu, char *tip )
|
||||
{
|
||||
if( !pymenu )
|
||||
return;
|
||||
|
||||
if( pymenu->tooltip )
|
||||
MEM_freeN( pymenu->tooltip );
|
||||
pymenu->tooltip = BLI_strdup( tip );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* bpymenu_AddEntry:
|
||||
* try to find an existing pymenu entry with the given type and name;
|
||||
* if found, update it with new info, otherwise create a new one and fill it.
|
||||
*/
|
||||
static BPyMenu *bpymenu_AddEntry( short group, short version, char *name,
|
||||
char *fname, int is_userdir, char *tooltip )
|
||||
{
|
||||
BPyMenu *menu, *next = NULL, **iter;
|
||||
int nameclash = 0;
|
||||
|
||||
if( ( group < 0 ) || ( group >= PYMENU_TOTAL ) )
|
||||
return NULL;
|
||||
if( !name || !fname )
|
||||
return NULL;
|
||||
|
||||
menu = bpymenu_FindEntry( group, name ); /* already exists? */
|
||||
|
||||
/* if a menu with this name already exists in the same group:
|
||||
* - if one script is in the default dir and the other in U.pythondir,
|
||||
* accept and let the new one override the other.
|
||||
* - otherwise, report the error and return NULL. */
|
||||
if( menu ) {
|
||||
if( menu->dir < is_userdir ) { /* new one is in U.pythondir */
|
||||
nameclash = 1;
|
||||
if( menu->name )
|
||||
MEM_freeN( menu->name );
|
||||
if( menu->filename )
|
||||
MEM_freeN( menu->filename );
|
||||
if( menu->tooltip )
|
||||
MEM_freeN( menu->tooltip );
|
||||
if( menu->submenus )
|
||||
bpymenu_RemoveAllSubEntries( menu->submenus );
|
||||
next = menu->next;
|
||||
} else { /* they are in the same dir */
|
||||
if (DEBUG) {
|
||||
fprintf(stderr, "\n\
|
||||
Warning: script %s's menu name is already in use.\n\
|
||||
Edit the script and change its \n\
|
||||
Name: '%s'\n\
|
||||
field, please.\n\
|
||||
Note: if you really want to have two scripts for the same menu with\n\
|
||||
the same name, keep one in the default dir and the other in\n\
|
||||
the user defined dir (only the later will be registered).\n", fname, name);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
} else
|
||||
menu = MEM_mallocN( sizeof( BPyMenu ), "pymenu" );
|
||||
|
||||
if( !menu )
|
||||
return NULL;
|
||||
|
||||
menu->name = BLI_strdup( name );
|
||||
menu->version = version;
|
||||
menu->filename = BLI_strdup( fname );
|
||||
menu->tooltip = NULL;
|
||||
if( tooltip )
|
||||
menu->tooltip = BLI_strdup( tooltip );
|
||||
menu->dir = is_userdir;
|
||||
menu->submenus = NULL;
|
||||
menu->next = next; /* non-NULL if menu already existed */
|
||||
|
||||
if( nameclash )
|
||||
return menu; /* no need to place it, it's already at the list */
|
||||
else { /* insert the new entry in its correct position at the table */
|
||||
BPyMenu *prev = NULL;
|
||||
char *s = NULL;
|
||||
|
||||
iter = &BPyMenuTable[group];
|
||||
while( *iter ) {
|
||||
s = ( *iter )->name;
|
||||
if( s )
|
||||
if( strcmp( menu->name, s ) < 0 )
|
||||
break; /* sort by names */
|
||||
prev = *iter;
|
||||
iter = &( ( *iter )->next );
|
||||
}
|
||||
|
||||
if( *iter ) { /* prepend */
|
||||
menu->next = *iter;
|
||||
if( prev )
|
||||
prev->next = menu;
|
||||
else
|
||||
BPyMenuTable[group] = menu; /* is first entry */
|
||||
} else
|
||||
*iter = menu; /* append */
|
||||
}
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
/* bpymenu_AddSubEntry:
|
||||
* add a submenu to an existing python menu.
|
||||
*/
|
||||
static int bpymenu_AddSubEntry( BPyMenu * mentry, char *name, char *arg )
|
||||
{
|
||||
BPySubMenu *smenu, **iter;
|
||||
|
||||
smenu = MEM_mallocN( sizeof( BPySubMenu ), "pysubmenu" );
|
||||
if( !smenu )
|
||||
return -1;
|
||||
|
||||
smenu->name = BLI_strdup( name );
|
||||
smenu->arg = BLI_strdup( arg );
|
||||
smenu->next = NULL;
|
||||
|
||||
if( !smenu->name || !smenu->arg )
|
||||
return -1;
|
||||
|
||||
iter = &( mentry->submenus );
|
||||
while( *iter )
|
||||
iter = &( ( *iter )->next );
|
||||
|
||||
*iter = smenu;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* bpymenu_CreateFromFile:
|
||||
* parse the bpymenus data file where Python menu data is stored;
|
||||
* based on this data, create and fill the pymenu structs.
|
||||
*/
|
||||
static int bpymenu_CreateFromFile( void )
|
||||
{
|
||||
FILE *fp;
|
||||
char line[255], w1[255], w2[255], tooltip[255], *tip;
|
||||
char *homedir = NULL;
|
||||
int parsing, version, is_userdir;
|
||||
short group;
|
||||
BPyMenu *pymenu = NULL;
|
||||
|
||||
/* init global bpymenu table (it is a list of pointers to struct BPyMenus
|
||||
* for each available cathegory: import, export, etc.) */
|
||||
for( group = 0; group < PYMENU_TOTAL; group++ )
|
||||
BPyMenuTable[group] = NULL;
|
||||
|
||||
/* let's try to open the file with bpymenu data */
|
||||
homedir = bpy_gethome(0);
|
||||
if (!homedir) {
|
||||
if( DEBUG )
|
||||
fprintf(stderr,
|
||||
"BPyMenus error: couldn't open config file Bpymenus: no home dir.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
BLI_make_file_string( "/", line, homedir, BPYMENU_DATAFILE );
|
||||
|
||||
fp = fopen( line, "rb" );
|
||||
|
||||
if( !fp ) {
|
||||
if( DEBUG )
|
||||
fprintf(stderr, "BPyMenus error: couldn't open config file %s.\n", line );
|
||||
return -1;
|
||||
}
|
||||
|
||||
fgets( line, 255, fp ); /* header */
|
||||
|
||||
/* check if the U.pythondir we saved at the file is different from the
|
||||
* current one. If so, return to force updating from dirs */
|
||||
w1[0] = '\0';
|
||||
fscanf( fp, "# User defined scripts dir: %[^\n]\n", w1 );
|
||||
if( w1 ) {
|
||||
char upythondir[FILE_MAXDIR];
|
||||
|
||||
BLI_strncpy(upythondir, U.pythondir, FILE_MAXDIR);
|
||||
BLI_convertstringcode(upythondir, G.sce, 0);
|
||||
if( strcmp( w1, upythondir ) != 0 )
|
||||
return -1;
|
||||
w1[0] = '\0';
|
||||
}
|
||||
|
||||
while( fgets( line, 255, fp ) ) { /* parsing file lines */
|
||||
|
||||
switch ( line[0] ) { /* check first char */
|
||||
case '#': /* comment */
|
||||
continue;
|
||||
break;
|
||||
case '\n':
|
||||
continue;
|
||||
break;
|
||||
default:
|
||||
parsing = sscanf( line, "%s {\n", w1 ); /* menu group */
|
||||
break;
|
||||
}
|
||||
|
||||
if( parsing == 1 ) { /* got menu group string */
|
||||
group = (short)bpymenu_group_atoi( w1 );
|
||||
if( group < 0 && DEBUG ) { /* invalid type */
|
||||
fprintf(stderr,
|
||||
"BPyMenus error parsing config file: wrong group: %s,\n\
|
||||
will use 'Misc'.\n", w1 );
|
||||
}
|
||||
} else
|
||||
continue;
|
||||
|
||||
for(;;) {
|
||||
tip = NULL; /* optional tooltip */
|
||||
fgets( line, 255, fp );
|
||||
if( line[0] == '}' )
|
||||
break;
|
||||
else if( line[0] == '\n' )
|
||||
continue;
|
||||
else if( line[0] == '\'' ) { /* menu entry */
|
||||
parsing =
|
||||
sscanf( line,
|
||||
"'%[^']' %d %s %d '%[^']'\n",
|
||||
w1, &version, w2, &is_userdir,
|
||||
tooltip );
|
||||
|
||||
if( parsing <= 0 ) { /* invalid line, get rid of it */
|
||||
fgets( line, 255, fp );
|
||||
} else if( parsing == 5 )
|
||||
tip = tooltip; /* has tooltip */
|
||||
|
||||
pymenu = bpymenu_AddEntry( group,
|
||||
( short ) version,
|
||||
w1, w2, is_userdir,
|
||||
tip );
|
||||
if( !pymenu ) {
|
||||
puts( "BPyMenus error: couldn't create bpymenu entry.\n" );
|
||||
fclose( fp );
|
||||
return -1;
|
||||
}
|
||||
} else if( line[0] == '|' && line[1] == '_' ) { /* menu sub-entry */
|
||||
if( !pymenu )
|
||||
continue; /* no menu yet, skip this line */
|
||||
sscanf( line, "|_%[^:]: %s\n", w1, w2 );
|
||||
bpymenu_AddSubEntry( pymenu, w1, w2 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose( fp );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* bpymenu_WriteDataFile:
|
||||
* writes the registered scripts info to the user's home dir, for faster
|
||||
* access when the scripts dir hasn't changed.
|
||||
*/
|
||||
static void bpymenu_WriteDataFile( void )
|
||||
{
|
||||
BPyMenu *pymenu;
|
||||
BPySubMenu *smenu;
|
||||
FILE *fp;
|
||||
char fname[FILE_MAXDIR], *homedir;
|
||||
int i;
|
||||
|
||||
homedir = bpy_gethome(0);
|
||||
|
||||
if (!homedir) {
|
||||
if( DEBUG )
|
||||
fprintf(stderr,
|
||||
"BPyMenus error: couldn't write Bpymenus file: no home dir.\n\n");
|
||||
return;
|
||||
}
|
||||
|
||||
BLI_make_file_string( "/", fname, homedir, BPYMENU_DATAFILE );
|
||||
|
||||
fp = fopen( fname, "w" );
|
||||
if( !fp ) {
|
||||
if( DEBUG )
|
||||
fprintf(stderr, "BPyMenus error: couldn't write %s file.\n\n",
|
||||
fname );
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf( fp,
|
||||
"# Blender: registered menu entries for bpython scripts\n" );
|
||||
|
||||
if (U.pythondir[0] != '\0' &&
|
||||
strcmp(U.pythondir, "/") != 0 && strcmp(U.pythondir, "//") != 0)
|
||||
{
|
||||
char upythondir[FILE_MAXDIR];
|
||||
|
||||
BLI_strncpy(upythondir, U.pythondir, FILE_MAXDIR);
|
||||
BLI_convertstringcode(upythondir, G.sce, 0);
|
||||
fprintf( fp, "# User defined scripts dir: %s\n", upythondir );
|
||||
}
|
||||
|
||||
for( i = 0; i < PYMENU_TOTAL; i++ ) {
|
||||
pymenu = BPyMenuTable[i];
|
||||
if( !pymenu )
|
||||
continue;
|
||||
fprintf( fp, "\n%s {\n", BPyMenu_group_itoa( (short)i ) );
|
||||
while( pymenu ) {
|
||||
fprintf( fp, "'%s' %d %s %d", pymenu->name,
|
||||
pymenu->version, pymenu->filename,
|
||||
pymenu->dir );
|
||||
if( pymenu->tooltip )
|
||||
fprintf( fp, " '%s'\n", pymenu->tooltip );
|
||||
else
|
||||
fprintf( fp, "\n" );
|
||||
smenu = pymenu->submenus;
|
||||
while( smenu ) {
|
||||
fprintf( fp, "|_%s: %s\n", smenu->name,
|
||||
smenu->arg );
|
||||
smenu = smenu->next;
|
||||
}
|
||||
pymenu = pymenu->next;
|
||||
}
|
||||
fprintf( fp, "}\n" );
|
||||
}
|
||||
|
||||
fclose( fp );
|
||||
return;
|
||||
}
|
||||
|
||||
/* BPyMenu_PrintAllEntries:
|
||||
* useful for debugging.
|
||||
*/
|
||||
void BPyMenu_PrintAllEntries( void )
|
||||
{
|
||||
BPyMenu *pymenu;
|
||||
BPySubMenu *smenu;
|
||||
int i;
|
||||
|
||||
printf( "# Blender: registered menu entries for bpython scripts\n" );
|
||||
|
||||
for( i = 0; i < PYMENU_TOTAL; i++ ) {
|
||||
pymenu = BPyMenuTable[i];
|
||||
printf( "\n%s {\n", BPyMenu_group_itoa( (short)i ) );
|
||||
while( pymenu ) {
|
||||
printf( "'%s' %d %s %d", pymenu->name, pymenu->version,
|
||||
pymenu->filename, pymenu->dir );
|
||||
if( pymenu->tooltip )
|
||||
printf( " '%s'\n", pymenu->tooltip );
|
||||
else
|
||||
printf( "\n" );
|
||||
smenu = pymenu->submenus;
|
||||
while( smenu ) {
|
||||
printf( "|_%s: %s\n", smenu->name,
|
||||
smenu->arg );
|
||||
smenu = smenu->next;
|
||||
}
|
||||
pymenu = pymenu->next;
|
||||
}
|
||||
printf( "}\n" );
|
||||
}
|
||||
}
|
||||
|
||||
/* bpymenu_ParseFile:
|
||||
* recursively scans folders looking for scripts to register.
|
||||
*
|
||||
* This function scans the scripts directory looking for .py files with the
|
||||
* right header and menu info, using that to fill the bpymenu structs.
|
||||
* is_userdir defines if the script is in the default scripts dir or the
|
||||
* user defined one (U.pythondir: is_userdir == 1).
|
||||
* Speed is important.
|
||||
*
|
||||
* The first line of the script must be '#!BPY'.
|
||||
* The header registration lines must appear between the first pair of
|
||||
* '\"\"\"' and follow this order (the single-quotes are part of
|
||||
* the format):
|
||||
*
|
||||
* # \"\"\"<br>
|
||||
* # Name: 'script name for the menu'
|
||||
* # Blender: <code>short int</code> (minimal Blender version)
|
||||
* # Group: 'group name' (defines menu)
|
||||
* # Submenu: 'submenu name' related_1word_arg
|
||||
* # Tooltip: 'tooltip for the menu'
|
||||
* # \"\"\"
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* - Commenting out header lines with "#" is optional, but recommended.
|
||||
* - 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;
|
||||
* - Line length must be less than 99.
|
||||
*/
|
||||
static int bpymenu_ParseFile(FILE *file, char *fname, int is_userdir)
|
||||
{
|
||||
char line[100];
|
||||
char head[100];
|
||||
char middle[100];
|
||||
char tail[100];
|
||||
int matches;
|
||||
int parser_state;
|
||||
|
||||
char script_name[100];
|
||||
int script_version = 1;
|
||||
int script_group;
|
||||
|
||||
BPyMenu *scriptMenu = NULL;
|
||||
|
||||
if (file != NULL) {
|
||||
parser_state = 1; /* state of parser, 0 to terminate */
|
||||
|
||||
while ((parser_state != 0) && (fgets(line, 100, file) != NULL)) {
|
||||
|
||||
switch (parser_state) {
|
||||
|
||||
case 1: /* !BPY */
|
||||
if (strncmp(line, "#!BPY", 5) == 0) {
|
||||
parser_state++;
|
||||
} else {
|
||||
parser_state = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: /* \"\"\" */
|
||||
if ((strstr(line, "\"\"\""))) {
|
||||
parser_state++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: /* Name: 'script name for the menu' */
|
||||
matches = sscanf(line, "%[^']'%[^']'%c", head, script_name, tail);
|
||||
if ((matches == 3) && (strstr(head, "Name:") != NULL)) {
|
||||
parser_state++;
|
||||
} else {
|
||||
if (DEBUG)
|
||||
fprintf(stderr, "BPyMenus error: Wrong 'Name' line: %s\n", fname);
|
||||
parser_state = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4: /* Blender: <short int> */
|
||||
matches = sscanf(line, "%[^1234567890]%i%c", head, &script_version,
|
||||
tail);
|
||||
if (matches == 3) {
|
||||
parser_state++;
|
||||
} else {
|
||||
if (DEBUG)
|
||||
fprintf(stderr,"BPyMenus error: Wrong 'Blender' line: %s\n",fname);
|
||||
parser_state = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 5: /* Group: 'group name' */
|
||||
matches = sscanf(line, "%[^']'%[^']'%c", head, middle, tail);
|
||||
if ((matches == 3) && (strstr(head, "Group:") != NULL)) {
|
||||
script_group = bpymenu_group_atoi(middle);
|
||||
if (script_group < 0) {
|
||||
if (DEBUG)
|
||||
fprintf(stderr, "BPyMenus error: Unknown group \"%s\": %s\n",
|
||||
middle, fname);
|
||||
parser_state = 0;
|
||||
}
|
||||
|
||||
else { /* register script */
|
||||
scriptMenu = bpymenu_AddEntry((short)script_group,
|
||||
(short int)script_version, script_name, fname, is_userdir,NULL);
|
||||
if (scriptMenu == NULL) {
|
||||
if (DEBUG)
|
||||
fprintf(stderr,
|
||||
"BPyMenus error: Couldn't create entry for: %s\n", fname);
|
||||
parser_state = 0;
|
||||
} else {
|
||||
parser_state++;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if (DEBUG)
|
||||
fprintf(stderr, "BPyMenus error: Wrong 'Group' line: %s\n",fname);
|
||||
parser_state = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 6: /* optional elements */
|
||||
/* Submenu: 'submenu name' related_1word_arg */
|
||||
matches = sscanf(line, "%[^']'%[^']'%s\n", head, middle, tail);
|
||||
if ((matches == 3) && (strstr(head, "Submenu:") != NULL)) {
|
||||
bpymenu_AddSubEntry(scriptMenu, middle, tail);
|
||||
} else {
|
||||
/* Tooltip: 'tooltip for the menu */
|
||||
matches = sscanf(line, "%[^']'%[^']'%c", head, middle, tail);
|
||||
if ((matches == 3) && ((strstr(head, "Tooltip:") != NULL) ||
|
||||
(strstr(head, "Tip:") != NULL))) {
|
||||
bpymenu_set_tooltip(scriptMenu, middle);
|
||||
}
|
||||
parser_state = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
parser_state = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else { /* shouldn't happen, it's checked in bpymenus_ParseDir */
|
||||
if (DEBUG)
|
||||
fprintf(stderr, "BPyMenus error: Couldn't open %s.\n", fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* bpymenu_ParseDir:
|
||||
* recursively scans folders looking for scripts to register.
|
||||
*
|
||||
* This function scans the scripts directory looking for .py files with the
|
||||
* right header and menu info.
|
||||
* - is_userdir defines if the script is in the default scripts dir or the
|
||||
* user defined one (U.pythondir: is_userdir == 1);
|
||||
* - parentdir is the parent dir name to store as part of the script filename,
|
||||
* if we're down a subdir.
|
||||
* Speed is important.
|
||||
*/
|
||||
static int bpymenu_ParseDir(char *dirname, char *parentdir, int is_userdir )
|
||||
{
|
||||
DIR *dir;
|
||||
FILE *file = NULL;
|
||||
struct dirent *de;
|
||||
struct stat status;
|
||||
char *file_extension;
|
||||
char path[FILE_MAX];
|
||||
char subdir[FILE_MAX];
|
||||
char *s = NULL;
|
||||
|
||||
dir = opendir(dirname);
|
||||
|
||||
if (dir != NULL) {
|
||||
while ((de = readdir(dir)) != NULL) {
|
||||
|
||||
/* skip files and dirs starting with '.' or 'bpy' */
|
||||
if ((de->d_name[0] == '.') || !strncmp(de->d_name, "bpy", 3)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BLI_make_file_string("/", path, dirname, de->d_name);
|
||||
|
||||
if (stat(path, &status) != 0) {
|
||||
if (DEBUG)
|
||||
fprintf(stderr, "stat %s failed: %s\n", path, strerror(errno));
|
||||
}
|
||||
|
||||
if (S_ISREG(status.st_mode)) { /* is file */
|
||||
|
||||
file_extension = strstr(de->d_name, ".py");
|
||||
|
||||
if (file_extension && *(file_extension + 3) == '\0') {
|
||||
file = fopen(path, "rb");
|
||||
|
||||
if (file) {
|
||||
s = de->d_name;
|
||||
if (parentdir) {
|
||||
/* Join parentdir and de->d_name */
|
||||
BLI_join_dirfile(subdir, parentdir, de->d_name);
|
||||
|
||||
s = subdir;
|
||||
}
|
||||
bpymenu_ParseFile(file, s, is_userdir);
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
else {
|
||||
if (DEBUG)
|
||||
fprintf(stderr, "BPyMenus error: Couldn't open %s.\n", path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (S_ISDIR(status.st_mode)) { /* is subdir */
|
||||
Dirs_Number++;
|
||||
Dir_Depth++;
|
||||
if (Dirs_Number > MAX_DIR_NUMBER) {
|
||||
if (DEBUG) {
|
||||
fprintf(stderr, "BPyMenus error: too many subdirs.\n");
|
||||
}
|
||||
closedir(dir);
|
||||
return -1;
|
||||
}
|
||||
else if (Dir_Depth > MAX_DIR_DEPTH) {
|
||||
if (DEBUG)
|
||||
fprintf(stderr,
|
||||
"BPyMenus error: max depth reached traversing dir tree.\n");
|
||||
closedir(dir);
|
||||
return -1;
|
||||
}
|
||||
s = de->d_name;
|
||||
if (parentdir) {
|
||||
/* Join parentdir and de->d_name */
|
||||
BLI_join_dirfile(subdir, parentdir, de->d_name);
|
||||
s = subdir;
|
||||
}
|
||||
if (bpymenu_ParseDir(path, s, is_userdir) == -1) {
|
||||
closedir(dir);
|
||||
return -1;
|
||||
}
|
||||
Dir_Depth--;
|
||||
}
|
||||
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
else { /* open directory stream failed */
|
||||
if (DEBUG)
|
||||
fprintf(stderr, "opendir %s failed: %s\n", dirname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bpymenu_GetStatMTime( char *name, int is_file, time_t * mtime )
|
||||
{
|
||||
struct stat st;
|
||||
int result;
|
||||
|
||||
result = stat( name, &st );
|
||||
|
||||
if( result == -1 )
|
||||
return -1;
|
||||
|
||||
if( is_file ) {
|
||||
if( !S_ISREG( st.st_mode ) )
|
||||
return -2;
|
||||
} else if( !S_ISDIR( st.st_mode ) )
|
||||
return -2;
|
||||
|
||||
*mtime = st.st_mtime;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* BPyMenu_Init:
|
||||
* import the bpython menus data to Blender, either from:
|
||||
* - the BPYMENU_DATAFILE file (?/.blender/Bpymenus) or
|
||||
* - the scripts dir(s), case newer than the datafile (then update the file).
|
||||
* then fill the bpymenu table with this data.
|
||||
* if param usedir != 0, then the data is recreated from the dir(s) anyway.
|
||||
*/
|
||||
int BPyMenu_Init( int usedir )
|
||||
{
|
||||
char fname[FILE_MAXDIR];
|
||||
char dirname[FILE_MAXDIR];
|
||||
char upythondir[FILE_MAXDIR];
|
||||
char *upydir = U.pythondir, *sdir = NULL;
|
||||
time_t time_dir1 = 0, time_dir2 = 0, time_file = 0;
|
||||
int stat_dir1 = 0, stat_dir2 = 0, stat_file = 0;
|
||||
int i;
|
||||
|
||||
DEBUG = G.f & G_DEBUG; /* is Blender in debug mode (started with -d) ? */
|
||||
|
||||
/* init global bpymenu table (it is a list of pointers to struct BPyMenus
|
||||
* for each available group: import, export, etc.) */
|
||||
for( i = 0; i < PYMENU_TOTAL; i++ )
|
||||
BPyMenuTable[i] = NULL;
|
||||
|
||||
if( DEBUG )
|
||||
fprintf(stdout, "\nRegistering scripts in Blender menus ...\n\n" );
|
||||
|
||||
if( U.pythondir[0] == '\0') {
|
||||
upydir = NULL;
|
||||
}
|
||||
else if (strcmp(U.pythondir, "/") == 0 || strcmp(U.pythondir, "//") == 0) {
|
||||
/* these are not accepted to prevent possible slight slowdowns on startup;
|
||||
* they should not be used as user defined scripts dir, anyway, also from
|
||||
* speed considerations, since they'd not be dedicated scripts dirs */
|
||||
if (DEBUG) fprintf(stderr,
|
||||
"BPyMenus: invalid user defined Python scripts dir: \"/\" or \"//\".\n");
|
||||
upydir = NULL;
|
||||
}
|
||||
else {
|
||||
BLI_strncpy(upythondir, upydir, FILE_MAXDIR);
|
||||
BLI_convertstringcode(upythondir, G.sce, 0);
|
||||
}
|
||||
|
||||
sdir = bpy_gethome(1);
|
||||
|
||||
if (sdir) {
|
||||
BLI_strncpy(dirname, sdir, FILE_MAXDIR);
|
||||
stat_dir1 = bpymenu_GetStatMTime( dirname, 0, &time_dir1 );
|
||||
|
||||
if( stat_dir1 < 0 ) {
|
||||
time_dir1 = 0;
|
||||
if( DEBUG ) {
|
||||
fprintf(stderr,
|
||||
"\nDefault scripts dir: %s:\n%s\n", dirname, strerror(errno));
|
||||
if( upydir )
|
||||
fprintf(stdout,
|
||||
"Getting scripts menu data from user defined dir: %s.\n",
|
||||
upythondir );
|
||||
}
|
||||
}
|
||||
}
|
||||
else stat_dir1 = -1;
|
||||
|
||||
if( upydir ) {
|
||||
stat_dir2 = bpymenu_GetStatMTime( upythondir, 0, &time_dir2 );
|
||||
|
||||
if( stat_dir2 < 0 ) {
|
||||
time_dir2 = 0;
|
||||
upydir = NULL;
|
||||
if( DEBUG )
|
||||
fprintf(stderr, "\nUser defined scripts dir: %s:\n%s.\n",
|
||||
upythondir, strerror( errno ) );
|
||||
if( stat_dir1 < 0 ) {
|
||||
if( DEBUG )
|
||||
fprintf(stderr, "\
|
||||
To have scripts in menus, please add them to the default scripts dir:\n\
|
||||
%s\n\
|
||||
and / or go to 'Info window -> File Paths tab' and set a valid path for\n\
|
||||
the user defined Python scripts dir.\n", dirname );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else stat_dir2 = -1;
|
||||
|
||||
if( ( stat_dir1 < 0 ) && ( stat_dir2 < 0 ) ) {
|
||||
if( DEBUG ) {
|
||||
fprintf(stderr, "\nCannot register scripts in menus, no scripts dir"
|
||||
" available.\nExpected default dir at: %s \n", dirname );
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (usedir) stat_file = -1;
|
||||
else { /* if we're not forced to use the dir */
|
||||
char *homedir = bpy_gethome(0);
|
||||
|
||||
if (homedir) {
|
||||
BLI_make_file_string( "/", fname, homedir, BPYMENU_DATAFILE );
|
||||
stat_file = bpymenu_GetStatMTime( fname, 1, &time_file );
|
||||
if( stat_file < 0 )
|
||||
time_file = 0;
|
||||
|
||||
/* comparing dates */
|
||||
|
||||
if((stat_file == 0)
|
||||
&& (time_file > time_dir1) && (time_file > time_dir2))
|
||||
{ /* file is newer */
|
||||
stat_file = bpymenu_CreateFromFile( ); /* -1 if an error occurred */
|
||||
if( !stat_file && DEBUG )
|
||||
fprintf(stdout,
|
||||
"Getting menu data for scripts from file:\n%s\n\n", fname );
|
||||
}
|
||||
else stat_file = -1;
|
||||
}
|
||||
else stat_file = -1; /* -1 to use dirs: didn't use file or it was corrupted */
|
||||
}
|
||||
|
||||
if( stat_file == -1 ) { /* use dirs */
|
||||
if( DEBUG ) {
|
||||
fprintf(stdout,
|
||||
"Getting menu data for scripts from dir(s):\ndefault: %s\n", dirname );
|
||||
if( upydir )
|
||||
fprintf(stdout, "user defined: %s\n", upythondir );
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
if( stat_dir1 == 0 ) {
|
||||
i = bpymenu_ParseDir( dirname, NULL, 0 );
|
||||
if (i == -1 && DEBUG)
|
||||
fprintf(stderr, "Default scripts dir does not seem valid.\n\n");
|
||||
}
|
||||
if( stat_dir2 == 0 ) {
|
||||
BLI_strncpy(dirname, U.pythondir, FILE_MAXDIR);
|
||||
BLI_convertstringcode(dirname, G.sce, 0);
|
||||
i = bpymenu_ParseDir( dirname, NULL, 1 );
|
||||
if (i == -1 && DEBUG)
|
||||
fprintf(stderr, "User defined scripts dir does not seem valid.\n\n");
|
||||
}
|
||||
|
||||
/* check if we got any data */
|
||||
for( i = 0; i < PYMENU_TOTAL; i++ )
|
||||
if( BPyMenuTable[i] )
|
||||
break;
|
||||
|
||||
/* if we got, recreate the file */
|
||||
if( i < PYMENU_TOTAL )
|
||||
bpymenu_WriteDataFile( );
|
||||
else if( DEBUG ) {
|
||||
fprintf(stderr, "\n\
|
||||
Warning: Registering scripts in menus -- no info found.\n\
|
||||
Either your scripts dirs have no .py scripts or the scripts\n\
|
||||
don't have a header with registration data.\n\
|
||||
Default scripts dir is:\n\
|
||||
%s\n", dirname );
|
||||
if( upydir )
|
||||
fprintf(stderr, "User defined scripts dir is: %s\n",
|
||||
upythondir );
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
128
source/blender/python/BPY_menus.h
Normal file
128
source/blender/python/BPY_menus.h
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* $Id: BPY_menus.h 12931 2007-12-17 18:20:48Z theeth $
|
||||
*
|
||||
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version. The Blender
|
||||
* Foundation also sells licenses for use in proprietary software under
|
||||
* the Blender License. See http://www.blender.org/BL/ for information
|
||||
* about this.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This is a new part of Blender.
|
||||
*
|
||||
* Contributor(s): Willian P. Germano, Matt Ebb
|
||||
*
|
||||
* ***** END GPL/BL DUAL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#ifndef BPY_MENUS_H
|
||||
#define BPY_MENUS_H
|
||||
|
||||
/* This header exposes BPyMenu related public declarations. The implementation
|
||||
* adds 'dynamic' menus to Blender, letting scripts register themselves in any
|
||||
* of a few pre-defined (trivial to upgrade) places in menus. These places or
|
||||
* slots are called groups here (Import, Export, etc). This is how it works:
|
||||
* - scripts at dirs user pref U.pythondir and .blender/scripts/ are scanned
|
||||
* for registration info.
|
||||
* - this data is also saved to a Bpymenus file at the user's .blender/ dir and
|
||||
* only re-created when the scripts folder gets modified.
|
||||
* - on start-up Blender uses this info to fill a table, which is used to
|
||||
* create the menu entries when they are needed (see header_info.c or
|
||||
* header_script.c, under source/blender/src/, for examples).
|
||||
*/
|
||||
|
||||
/* These two structs hold py menu/submenu info.
|
||||
* BPyMenu holds a script's name (as should appear in the menu) and filename,
|
||||
* plus an optional list of submenus. Each submenu is related to a string
|
||||
* (arg) that the script can get from the __script__ pydict, to know which
|
||||
* submenu was chosen. */
|
||||
|
||||
typedef struct BPySubMenu {
|
||||
char *name;
|
||||
char *arg;
|
||||
struct BPySubMenu *next;
|
||||
} BPySubMenu;
|
||||
|
||||
typedef struct BPyMenu {
|
||||
char *name;
|
||||
char *filename;
|
||||
char *tooltip;
|
||||
short version; /* Blender version */
|
||||
int dir; /* 0: default, 1: U.pythondir */
|
||||
struct BPySubMenu *submenus;
|
||||
struct BPyMenu *next;
|
||||
} BPyMenu;
|
||||
|
||||
/* Scripts can be added to only a few pre-defined places in menus, like
|
||||
* File->Import, File->Export, etc. (for speed and better control).
|
||||
* To make a new menu 'slot' available for scripts:
|
||||
* - add an entry to the enum below, before PYMENU_TOTAL, of course;
|
||||
* - update the bpymenu_group_atoi() and BPyMenu_group_itoa() functions in
|
||||
* BPY_menus.c;
|
||||
* - add the necessary code to the header_***.c file in
|
||||
* source/blender/src/, like done in header_info.c for import/export;
|
||||
*/
|
||||
typedef enum {
|
||||
PYMENU_ADD,/* creates new objects */
|
||||
PYMENU_ANIMATION,
|
||||
PYMENU_EXPORT,
|
||||
PYMENU_IMPORT,
|
||||
PYMENU_MATERIALS,
|
||||
PYMENU_MESH,
|
||||
PYMENU_MISC,
|
||||
PYMENU_OBJECT,
|
||||
PYMENU_RENDER,/* exporters to external renderers */
|
||||
PYMENU_SYSTEM,
|
||||
PYMENU_THEMES,
|
||||
PYMENU_UV,/* UV editing tools, to go in UV/Image editor space, 'UV' menu */
|
||||
PYMENU_IMAGE,/* Image editing tools, to go in UV/Image editor space, 'Image' menu */
|
||||
PYMENU_WIZARDS,/* complex 'app' scripts */
|
||||
|
||||
/* entries put after Wizards don't appear at the Scripts win->Scripts menu;
|
||||
* see define right below */
|
||||
|
||||
PYMENU_FACESELECT,
|
||||
PYMENU_WEIGHTPAINT,
|
||||
PYMENU_VERTEXPAINT,
|
||||
PYMENU_UVCALCULATION,
|
||||
PYMENU_ARMATURE,
|
||||
PYMENU_SCRIPTTEMPLATE,
|
||||
PYMENU_HELP,/*Main Help menu items - prob best to leave for 'official' ones*/
|
||||
PYMENU_HELPSYSTEM,/* Resources, troubleshooting, system tools */
|
||||
PYMENU_HELPWEBSITES,/* Help -> Websites submenu */
|
||||
PYMENU_MESHFACEKEY, /* face key in mesh editmode */
|
||||
PYMENU_ADDMESH, /* adds mesh */
|
||||
PYMENU_TOTAL
|
||||
} PYMENUHOOKS;
|
||||
|
||||
#define PYMENU_SCRIPTS_MENU_TOTAL (PYMENU_WIZARDS + 1)
|
||||
|
||||
/* BPyMenuTable holds all registered pymenus, as linked lists for each menu
|
||||
* where they can appear (see PYMENUHOOKS enum above).
|
||||
*/
|
||||
extern BPyMenu *BPyMenuTable[]; /* defined in BPY_menus.c */
|
||||
|
||||
/* public functions: */
|
||||
int BPyMenu_Init( int usedir );
|
||||
void BPyMenu_RemoveAllEntries( void );
|
||||
void BPyMenu_PrintAllEntries( void );
|
||||
char *BPyMenu_CreatePupmenuStr( BPyMenu * pym, short group );
|
||||
char *BPyMenu_group_itoa( short group );
|
||||
struct BPyMenu *BPyMenu_GetEntry( short group, short pos );
|
||||
|
||||
#endif /* BPY_MENUS_H */
|
||||
Reference in New Issue
Block a user