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/python')
-rw-r--r--source/blender/python/BPY_menus.c1118
-rw-r--r--source/blender/python/BPY_menus.h128
-rw-r--r--source/blender/python/Makefile34
-rw-r--r--source/blender/python/epy_doc_gen.py753
-rw-r--r--source/blender/python/generic/bpy_internal_import.h2
-rw-r--r--source/blender/python/intern/Makefile67
-rw-r--r--source/blender/python/intern/bpy.c2
-rw-r--r--source/blender/python/intern/bpy_operator_wrap.c1
-rw-r--r--source/blender/python/intern/bpy_rna.h1
-rw-r--r--source/blender/python/intern/bpy_ui.c69
-rw-r--r--source/blender/python/intern/bpy_ui.h31
-rw-r--r--source/blender/python/simple_enum_gen.py54
12 files changed, 2230 insertions, 30 deletions
diff --git a/source/blender/python/BPY_menus.c b/source/blender/python/BPY_menus.c
new file mode 100644
index 00000000000..b67f1e717da
--- /dev/null
+++ b/source/blender/python/BPY_menus.c
@@ -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;
+}
diff --git a/source/blender/python/BPY_menus.h b/source/blender/python/BPY_menus.h
new file mode 100644
index 00000000000..6cdea608b10
--- /dev/null
+++ b/source/blender/python/BPY_menus.h
@@ -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 */
diff --git a/source/blender/python/Makefile b/source/blender/python/Makefile
new file mode 100644
index 00000000000..43b6f91369b
--- /dev/null
+++ b/source/blender/python/Makefile
@@ -0,0 +1,34 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL 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.
+#
+# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) Blender Foundation.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Bounces make to subdirectories.
+
+SOURCEDIR = source/blender/python
+DIRS = intern generic
+
+include nan_subdirs.mk
diff --git a/source/blender/python/epy_doc_gen.py b/source/blender/python/epy_doc_gen.py
new file mode 100644
index 00000000000..f16c7504cb2
--- /dev/null
+++ b/source/blender/python/epy_doc_gen.py
@@ -0,0 +1,753 @@
+ # ***** BEGIN GPL 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.
+ #
+ # 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.
+ #
+ # Contributor(s): Campbell Barton
+ #
+ # #**** END GPL LICENSE BLOCK #****
+
+script_help_msg = '''
+Usage,
+run this script from blenders root path once you have compiled blender
+ ./blender.bin -P source/blender/python/epy_doc_gen.py
+
+This will generate python files in "./source/blender/python/doc/bpy"
+Generate html docs by running...
+
+ epydoc source/blender/python/doc/bpy/ -v \\
+ -o source/blender/python/doc/html \\
+ --inheritance=included \\
+ --no-sourcecode \\
+ --graph=classtree \\
+ --graph-font-size=8
+
+'''
+
+# if you dont have graphvis installed ommit the --graph arg.
+
+# GLOBALS['BASEDIR'] = './source/blender/python/doc'
+
+import os
+
+SUBMODULES = {}
+INIT_SUBMODULES = {} # store initialized files
+
+INIT_SUBMODULES_IMPORTS = {} # dont import the same module twice
+
+def append_package(package_path, mod_name):
+
+ init_path = os.path.join(os.path.dirname(package_path), "__init__.py")
+
+ # avoid double ups
+ if mod_name:
+ imports = INIT_SUBMODULES_IMPORTS.setdefault(init_path, [])
+ if mod_name in imports:
+ return
+ imports.append(mod_name)
+
+ try:
+ os.makedirs(os.path.dirname(init_path)) # make the dirs if they are not there
+ except:
+ pass
+
+ # Open the new file for the first time, otherwise keep it open.
+ f = INIT_SUBMODULES.get(init_path)
+ if f == None:
+ f = INIT_SUBMODULES[init_path] = open(init_path, 'w')
+
+ if mod_name:
+ f.write("import %s\n" % mod_name)
+
+ return f
+
+def append_package_recursive(package_path, BASEPATH):
+ '''
+ assume the last item of package_path will be a file (not a dir thats created)
+ '''
+
+ package_path = os.path.splitext(package_path)[0] # incase of .py
+
+ try:
+ os.makedirs(os.path.join(BASEPATH, os.path.dirname(package_path))) # make the dirs if they are not there
+ except:
+ pass
+
+ new_path = BASEPATH
+
+ for mod_name in package_path.split(os.sep):
+ init_path = os.path.join(new_path, "__init__.py")
+ new_path = os.path.join(new_path, mod_name)
+ append_package(init_path, mod_name)
+
+
+def open_submodule(subpath, BASEPATH):
+ '''
+ This is a utility function that lets us quickly add submodules
+ '''
+
+ # create all the package paths leading up to this module
+ append_package_recursive(subpath, BASEPATH)
+
+ module_name = os.path.basename( os.path.splitext(subpath)[0] )
+ mod_path = os.path.join(BASEPATH, subpath)
+
+ # Open the new file for the first time, otherwise keep it open.
+ f = SUBMODULES.get(mod_path)
+ if f == None:
+ f = SUBMODULES[mod_path] = open(mod_path, 'w')
+
+ f = open(mod_path, 'w')
+ return f
+
+def close_all():
+ for files in (INIT_SUBMODULES.values(), SUBMODULES.values()):
+ for f in files:
+ if f.name.endswith('.py'):
+ f_name = f.name
+ f.close()
+
+ f = open(f_name, 'a')
+ f.write("\ndel __package__\n") # annoying, no need do show this
+
+
+ f.close()
+
+
+def range_str(val):
+ if val < -10000000: return '-inf'
+ if val > 10000000: return 'inf'
+ if type(val)==float:
+ return '%g' % val
+ else:
+ return str(val)
+
+def get_array_str(length):
+ if length > 0: return ' array of %d items' % length
+ else: return ''
+
+def full_rna_struct_path(rna_struct):
+ '''
+ Needed when referencing one struct from another
+ '''
+ nested = rna_struct.nested
+ if nested:
+ return "%s.%s" % (full_rna_struct_path(nested), rna_struct.identifier)
+ else:
+ return rna_struct.identifier
+
+def rna_id_ignore(rna_id):
+ if rna_id == "rna_type":
+ return True
+
+ if "_OT_" in rna_id:
+ return True
+ if "_MT_" in rna_id:
+ return True
+ if "_PT_" in rna_id:
+ return True
+
+ return False
+
+def write_func(rna, ident, out, func_type):
+ # Keyword attributes
+ kw_args = [] # "foo = 1", "bar=0.5", "spam='ENUM'"
+ kw_arg_attrs = [] # "@type mode: int"
+
+ rna_struct= rna.rna_type
+
+ # Operators and functions work differently
+ if func_type=='OPERATOR':
+ rna_func_name = rna_struct.identifier.split("_OT_")[-1]
+ rna_func_desc = rna_struct.description.strip()
+ items = rna_struct.properties.items()
+ else:
+ rna_func_name = rna.identifier
+ rna_func_desc = rna.description.strip()
+ items = rna.parameters.items()
+
+
+ for rna_prop_identifier, rna_prop in items:
+ if rna_id_ignore(rna_prop_identifier):
+ continue
+
+ # clear vars
+ val = val_error = val_str = rna_prop_type = None
+
+ # ['rna_type', 'name', 'array_length', 'description', 'hard_max', 'hard_min', 'identifier', 'precision', 'readonly', 'soft_max', 'soft_min', 'step', 'subtype', 'type']
+ #rna_prop= op_rna.rna_type.properties[attr]
+ rna_prop_type = rna_prop.type.lower() # enum, float, int, boolean
+
+
+ # only for rna functions, operators should not get pointers as args
+ if rna_prop_type=='pointer':
+ rna_prop_type_refine = "L{%s}" % rna_prop.fixed_type.identifier
+ else:
+ # Collections/Arrays can have a srna type
+ rna_prop_srna_type = rna_prop.srna
+ if rna_prop_srna_type:
+ print(rna_prop_srna_type.identifier)
+ rna_prop_type_refine = "L{%s}" % rna_prop_srna_type.identifier
+ else:
+ rna_prop_type_refine = rna_prop_type
+
+ del rna_prop_srna_type
+
+
+ try: length = rna_prop.array_length
+ except: length = 0
+
+ array_str = get_array_str(length)
+
+ if rna_prop.use_return:
+ kw_type_str= "@rtype: %s%s" % (rna_prop_type_refine, array_str)
+ kw_param_str= "@return: %s" % (rna_prop.description.strip())
+ else:
+ kw_type_str= "@type %s: %s%s" % (rna_prop_identifier, rna_prop_type_refine, array_str)
+ kw_param_str= "@param %s: %s" % (rna_prop_identifier, rna_prop.description.strip())
+
+ kw_param_set = False
+
+ if func_type=='OPERATOR':
+ try:
+ val = getattr(rna, rna_prop_identifier)
+ val_error = False
+ except:
+ val = "'<UNDEFINED>'"
+ val_error = True
+
+
+ if val_error:
+ val_str = val
+ elif rna_prop_type=='float':
+ if length==0:
+ val_str= '%g' % val
+ if '.' not in val_str and '-' not in val_str: # value could be 1e-05
+ val_str += '.0'
+ else:
+ # array
+ val_str = str(tuple(val))
+
+ kw_param_str += (' in (%s, %s)' % (range_str(rna_prop.hard_min), range_str(rna_prop.hard_max)))
+ kw_param_set= True
+
+ elif rna_prop_type=='int':
+ if length==0:
+ val_str='%d' % val
+ else:
+ val_str = str(tuple(val))
+
+ # print(dir(rna_prop))
+ kw_param_str += (' in (%s, %s)' % (range_str(rna_prop.hard_min), range_str(rna_prop.hard_max)))
+ # These strings dont have a max length???
+ #kw_param_str += ' (maximum length of %s)' % (rna_prop.max_length)
+ kw_param_set= True
+
+ elif rna_prop_type=='boolean':
+ if length==0:
+ if val: val_str='True'
+ else: val_str='False'
+ else:
+ val_str = str(tuple(val))
+
+ elif rna_prop_type=='enum':
+ # no array here?
+ val_str="'%s'" % val
+ # Too cramped
+ kw_param_str += (' in (%s)' % ', '.join(rna_prop.items.keys()))
+
+ kw_param_set= True
+
+ elif rna_prop_type=='string':
+ # no array here?
+ val_str='"%s"' % val
+
+ # todo - collection - array
+ # print (rna_prop.type)
+
+ kw_args.append('%s = %s' % (rna_prop_identifier, val_str))
+
+ # stora
+ else:
+ # currently functions dont have a default value
+ if not rna_prop.use_return:
+ kw_args.append('%s' % (rna_prop_identifier))
+ else:
+ kw_param_set = True
+
+
+ # Same for operators and functions
+ kw_arg_attrs.append(kw_type_str)
+ if kw_param_set:
+ kw_arg_attrs.append(kw_param_str)
+
+
+
+ out.write(ident+'def %s(%s):\n' % (rna_func_name, ', '.join(kw_args)))
+ out.write(ident+'\t"""\n')
+
+ # Descriptions could be multiline
+ for rna_func_desc_line in rna_func_desc.split('\n'):
+ out.write(ident+'\t%s\n' % rna_func_desc_line.strip())
+
+ for desc in kw_arg_attrs:
+ out.write(ident+'\t%s\n' % desc)
+
+ # out.write(ident+'\t@rtype: None\n') # implicit
+ out.write(ident+'\t"""\n')
+
+
+
+def rna2epy(BASEPATH):
+
+ # Use for faster lookups
+ # use rna_struct.identifier as the key for each dict
+ rna_struct_dict = {} # store identifier:rna lookups
+ rna_full_path_dict = {} # store the result of full_rna_struct_path(rna_struct)
+ rna_children_dict = {} # store all rna_structs nested from here
+ rna_references_dict = {} # store a list of rna path strings that reference this type
+ rna_functions_dict = {} # store all functions directly in this type (not inherited)
+ rna_words = set()
+
+ # def write_func(rna_func, ident):
+
+
+ def write_struct(rna_struct, ident):
+ identifier = rna_struct.identifier
+
+ rna_base = rna_struct.base
+
+ if rna_base:
+ out.write(ident+ 'class %s(%s):\n' % (identifier, rna_base.identifier))
+ rna_base_prop_keys = rna_base.properties.keys() # could be cached
+ rna_base_func_keys = [f.identifier for f in rna_base.functions]
+ else:
+ out.write(ident+ 'class %s:\n' % identifier)
+ rna_base_prop_keys = []
+ rna_base_func_keys = []
+
+ out.write(ident+ '\t"""\n')
+
+ title = 'The %s Object' % rna_struct.name
+ description = rna_struct.description.strip()
+ out.write(ident+ '\t%s\n' % title)
+ out.write(ident+ '\t%s\n' % ('=' * len(title)))
+ out.write(ident+ '\t\t%s\n' % description)
+ rna_words.update(description.split())
+
+
+ # For convenience, give a list of all places were used.
+ rna_refs= rna_references_dict[identifier]
+
+ if rna_refs:
+ out.write(ident+ '\t\t\n')
+ out.write(ident+ '\t\tReferences\n')
+ out.write(ident+ '\t\t==========\n')
+
+ for rna_ref_string in rna_refs:
+ out.write(ident+ '\t\t\t- L{%s}\n' % rna_ref_string)
+
+ out.write(ident+ '\t\t\n')
+
+ else:
+ out.write(ident+ '\t\t\n')
+ out.write(ident+ '\t\t(no references to this struct found)\n')
+ out.write(ident+ '\t\t\n')
+
+ for rna_prop_identifier, rna_prop in rna_struct.properties.items():
+
+ if rna_prop_identifier=='RNA': continue
+ if rna_id_ignore(rna_prop_identifier): continue
+ if rna_prop_identifier in rna_base_prop_keys: continue # does this prop exist in our parent class, if so skip
+
+ rna_desc = rna_prop.description.strip()
+
+ if rna_desc: rna_words.update(rna_desc.split())
+ if not rna_desc: rna_desc = rna_prop.name
+ if not rna_desc: rna_desc = 'Note - No documentation for this property!'
+
+ rna_prop_type = rna_prop.type.lower()
+
+ if rna_prop_type=='collection': collection_str = 'Collection of '
+ else: collection_str = ''
+
+ # some collections have a srna for their own properties
+ # TODO - arrays, however this isnt used yet
+ rna_prop_srna_type = rna_prop.srna
+ if rna_prop_srna_type:
+ collection_str = "L{%s} %s" % (rna_prop_srna_type.identifier, collection_str)
+ del rna_prop_srna_type
+
+ try: rna_prop_ptr = rna_prop.fixed_type
+ except: rna_prop_ptr = None
+
+ try: length = rna_prop.array_length
+ except: length = 0
+
+ array_str = get_array_str(length)
+
+ if rna_prop.editable: readonly_str = ''
+ else: readonly_str = ' (readonly)'
+
+ if rna_prop_ptr: # Use the pointer type
+ out.write(ident+ '\t@ivar %s: %s\n' % (rna_prop_identifier, rna_desc))
+ out.write(ident+ '\t@type %s: %sL{%s}%s%s\n' % (rna_prop_identifier, collection_str, rna_prop_ptr.identifier, array_str, readonly_str))
+ else:
+ if rna_prop_type == 'enum':
+ if 0:
+ out.write(ident+ '\t@ivar %s: %s in (%s)\n' % (rna_prop_identifier, rna_desc, ', '.join(rna_prop.items.keys())))
+ else:
+ out.write(ident+ '\t@ivar %s: %s in...\n' % (rna_prop_identifier, rna_desc))
+ for e, e_rna_prop in rna_prop.items.items():
+ #out.write(ident+ '\t\t- %s: %s\n' % (e, e_rna_prop.description)) # XXX - segfaults, FIXME
+ out.write(ident+ '\t\t- %s\n' % e)
+
+ out.write(ident+ '\t@type %s: %s%s%s\n' % (rna_prop_identifier, rna_prop_type, array_str, readonly_str))
+ elif rna_prop_type == 'int' or rna_prop_type == 'float':
+ out.write(ident+ '\t@ivar %s: %s\n' % (rna_prop_identifier, rna_desc))
+ out.write(ident+ '\t@type %s: %s%s%s in [%s, %s]\n' % (rna_prop_identifier, rna_prop_type, array_str, readonly_str, range_str(rna_prop.hard_min), range_str(rna_prop.hard_max) ))
+ elif rna_prop_type == 'string':
+ out.write(ident+ '\t@ivar %s: %s (maximum length of %s)\n' % (rna_prop_identifier, rna_desc, rna_prop.max_length))
+ out.write(ident+ '\t@type %s: %s%s%s\n' % (rna_prop_identifier, rna_prop_type, array_str, readonly_str))
+ else:
+ out.write(ident+ '\t@ivar %s: %s\n' % (rna_prop_identifier, rna_desc))
+ out.write(ident+ '\t@type %s: %s%s%s\n' % (rna_prop_identifier, rna_prop_type, array_str, readonly_str))
+
+
+ out.write(ident+ '\t"""\n\n')
+
+
+ # Write functions
+ # for rna_func in rna_struct.functions: # Better ignore inherited (line below)
+ for rna_func in rna_functions_dict[identifier]:
+ if rna_func not in rna_base_func_keys:
+ write_func(rna_func, ident+'\t', out, 'FUNCTION')
+
+ out.write('\n')
+
+ # Now write children recursively
+ for child in rna_children_dict[identifier]:
+ write_struct(child, ident + '\t')
+
+
+
+ # out = open(target_path, 'w')
+ out = open_submodule("types.py", BASEPATH) # bpy.types
+
+ def base_id(rna_struct):
+ try: return rna_struct.base.identifier
+ except: return '' # invalid id
+
+ #structs = [(base_id(rna_struct), rna_struct.identifier, rna_struct) for rna_struct in bpy.doc.structs.values()]
+ '''
+ structs = []
+ for rna_struct in bpy.doc.structs.values():
+ structs.append( (base_id(rna_struct), rna_struct.identifier, rna_struct) )
+ '''
+ structs = []
+ for rna_type_name in dir(bpy.types):
+ rna_type = getattr(bpy.types, rna_type_name)
+
+ try: rna_struct = rna_type.bl_rna
+ except: rna_struct = None
+
+ if rna_struct:
+ #if not rna_type_name.startswith('__'):
+
+ identifier = rna_struct.identifier
+
+ if not rna_id_ignore(identifier):
+ structs.append( (base_id(rna_struct), identifier, rna_struct) )
+
+ # Simple lookup
+ rna_struct_dict[identifier] = rna_struct
+
+ # Store full rna path 'GameObjectSettings' -> 'Object.GameObjectSettings'
+ rna_full_path_dict[identifier] = full_rna_struct_path(rna_struct)
+
+ # Store a list of functions, remove inherited later
+ rna_functions_dict[identifier]= list(rna_struct.functions)
+
+
+ # fill in these later
+ rna_children_dict[identifier]= []
+ rna_references_dict[identifier]= []
+
+
+ else:
+ print("Ignoring", rna_type_name)
+
+
+ # Sucks but we need to copy this so we can check original parent functions
+ rna_functions_dict__copy = {}
+ for key, val in rna_functions_dict.items():
+ rna_functions_dict__copy[key] = val[:]
+
+
+ structs.sort() # not needed but speeds up sort below, setting items without an inheritance first
+
+ # Arrange so classes are always defined in the correct order
+ deps_ok = False
+ while deps_ok == False:
+ deps_ok = True
+ rna_done = set()
+
+ for i, (rna_base, identifier, rna_struct) in enumerate(structs):
+
+ rna_done.add(identifier)
+
+ if rna_base and rna_base not in rna_done:
+ deps_ok = False
+ data = structs.pop(i)
+ ok = False
+ while i < len(structs):
+ if structs[i][1]==rna_base:
+ structs.insert(i+1, data) # insert after the item we depend on.
+ ok = True
+ break
+ i+=1
+
+ if not ok:
+ print('Dependancy "%s" could not be found for "%s"' % (identifier, rna_base))
+
+ break
+
+ # Done ordering structs
+
+
+ # precalc vars to avoid a lot of looping
+ for (rna_base, identifier, rna_struct) in structs:
+
+ if rna_base:
+ rna_base_prop_keys = rna_struct_dict[rna_base].properties.keys() # could cache
+ rna_base_func_keys = [f.identifier for f in rna_struct_dict[rna_base].functions]
+ else:
+ rna_base_prop_keys = []
+ rna_base_func_keys= []
+
+ # rna_struct_path = full_rna_struct_path(rna_struct)
+ rna_struct_path = rna_full_path_dict[identifier]
+
+ for rna_prop_identifier, rna_prop in rna_struct.properties.items():
+
+ if rna_prop_identifier=='RNA': continue
+ if rna_id_ignore(rna_prop_identifier): continue
+ if rna_prop_identifier in rna_base_prop_keys: continue
+
+
+ for rna_prop_ptr in (getattr(rna_prop, "fixed_type", None), getattr(rna_prop, "srna", None)):
+ # Does this property point to me?
+ if rna_prop_ptr:
+ rna_references_dict[rna_prop_ptr.identifier].append( "%s.%s" % (rna_struct_path, rna_prop_identifier) )
+
+ for rna_func in rna_struct.functions:
+ for rna_prop_identifier, rna_prop in rna_func.parameters.items():
+
+ if rna_prop_identifier=='RNA': continue
+ if rna_id_ignore(rna_prop_identifier): continue
+ if rna_prop_identifier in rna_base_func_keys: continue
+
+
+ try: rna_prop_ptr = rna_prop.fixed_type
+ except: rna_prop_ptr = None
+
+ # Does this property point to me?
+ if rna_prop_ptr:
+ rna_references_dict[rna_prop_ptr.identifier].append( "%s.%s" % (rna_struct_path, rna_func.identifier) )
+
+
+ # Store nested children
+ nested = rna_struct.nested
+ if nested:
+ rna_children_dict[nested.identifier].append(rna_struct)
+
+
+ if rna_base:
+ rna_funcs = rna_functions_dict[identifier]
+ if rna_funcs:
+ # Remove inherited functions if we have any
+ rna_base_funcs = rna_functions_dict__copy[rna_base]
+ rna_funcs[:] = [f for f in rna_funcs if f not in rna_base_funcs]
+
+ rna_functions_dict__copy.clear()
+ del rna_functions_dict__copy
+
+ # Sort the refs, just reads nicer
+ for rna_refs in rna_references_dict.values():
+ rna_refs.sort()
+
+ for (rna_base, identifier, rna_struct) in structs:
+ if rna_struct.nested:
+ continue
+
+ write_struct(rna_struct, '')
+
+
+ out.write('\n')
+ out.close()
+
+ # # We could also just run....
+ # os.system('epydoc source/blender/python/doc/rna.py -o ./source/blender/python/doc/html -v')
+
+ target_path = os.path.join(BASEPATH, "dump.py") # XXX - used for other funcs
+
+ # Write graphviz
+ out= open(target_path.replace('.py', '.dot'), 'w')
+ out.write('digraph "rna data api" {\n')
+ out.write('\tnode [style=filled, shape = "box"];\n')
+ out.write('\toverlap=false;\n')
+ out.write('\trankdir = LR;\n')
+ out.write('\tsplines=true;\n')
+ out.write('\tratio=auto;\n')
+
+
+
+ out.write('\tsize="10,10"\n')
+ #out.write('\tpage="8.5,11"\n')
+ #out.write('\tcenter=""\n')
+
+ def isop(rna_struct):
+ return '_OT_' in rna_struct.identifier
+
+
+ for (rna_base, identifier, rna_struct) in structs:
+ if isop(rna_struct):
+ continue
+
+ base = rna_struct.base
+
+
+ out.write('\t"%s";\n' % identifier)
+
+ for (rna_base, identifier, rna_struct) in structs:
+
+ if isop(rna_struct):
+ continue
+
+ base = rna_struct.base
+
+ if base and not isop(base):
+ out.write('\t"%s" -> "%s" [label="(base)" weight=1.0];\n' % (base.identifier, identifier))
+
+ nested = rna_struct.nested
+ if nested and not isop(nested):
+ out.write('\t"%s" -> "%s" [label="(nested)" weight=1.0];\n' % (nested.identifier, identifier))
+
+
+
+ rna_refs= rna_references_dict[identifier]
+
+ for rna_ref_string in rna_refs:
+
+ if '_OT_' in rna_ref_string:
+ continue
+
+ ref = rna_ref_string.split('.')[-2]
+ out.write('\t"%s" -> "%s" [label="%s" weight=0.01];\n' % (ref, identifier, rna_ref_string))
+
+
+ out.write('}\n')
+ out.close()
+
+ # # We could also just run....
+ # os.system('dot source/blender/python/doc/rna.dot -Tsvg -o ./source/blender/python/doc/rna.svg')
+
+
+ out= open(target_path.replace('.py', '.words'), 'w')
+ rna_words = list(rna_words)
+ rna_words.sort()
+ for w in rna_words:
+ out.write('%s\n' % w)
+
+
+def op2epy(BASEPATH):
+ # out = open(target_path, 'w')
+
+ op_mods = dir(bpy.ops)
+ op_mods.remove('add')
+ op_mods.remove('remove')
+
+ for op_mod_name in sorted(op_mods):
+ if op_mod_name.startswith('__'):
+ continue
+
+ # open the submodule
+ mod_path = os.path.join("ops", op_mod_name + ".py")
+ out = open_submodule(mod_path, BASEPATH)
+
+
+ op_mod = getattr(bpy.ops, op_mod_name)
+ operators = dir(op_mod)
+ for op in sorted(operators):
+ # rna = getattr(bpy.types, op).bl_rna
+ rna = getattr(op_mod, op).get_rna()
+ write_func(rna, '', out, 'OPERATOR')
+
+ out.write('\n')
+ out.close()
+
+def misc2epy(BASEPATH):
+ '''
+ Hard coded modules, try to avoid adding stuff here
+ '''
+
+ f = append_package(os.path.join(BASEPATH, ""), ""); # add a slash on the end of the base path
+ f.write('''
+"""
+@type data: L{bpy.types.Main}
+@var data: blender data is accessed from here
+"""
+''')
+
+ f = open_submodule("props.py", BASEPATH)
+ f.write('''
+MAX_INT= 2**31
+MAX_FLOAT= 1e+37
+def BoolProperty(attr, name="", description="", default=False):
+ """
+ return a new bool property
+ """
+def IntProperty(attr, name="", description="", min=-MAX_INT, max=MAX_INT, soft_min=-MAX_INT, soft_max=MAX_INT, default=0):
+ """
+ return a new int property
+ """
+def FloatProperty(attr, name="", description="", min=-MAX_FLOAT, max=MAX_FLOAT, soft_min=-MAX_FLOAT, soft_max=MAX_FLOAT, default=0.0):
+ """
+ return a new float property
+ """
+def StringProperty(attr, name="", description="", maxlen=0, default=""):
+ """
+ return a new string property
+ """
+def EnumProperty(attr, items, name="", description="", default=""):
+ """
+ return a new enum property
+ """
+''')
+
+
+if __name__ == '__main__':
+ if 'bpy' not in dir():
+ print("\nError, this script must run from inside blender2.5")
+ print(script_help_msg)
+ else:
+ misc2epy('source/blender/python/doc/bpy') # first to write in info in some of the modules.
+ rna2epy('source/blender/python/doc/bpy')
+ op2epy('source/blender/python/doc/bpy')
+
+
+ close_all()
+
+ import sys
+ sys.exit()
diff --git a/source/blender/python/generic/bpy_internal_import.h b/source/blender/python/generic/bpy_internal_import.h
index 0ef31229f8d..eb49a3e7c6c 100644
--- a/source/blender/python/generic/bpy_internal_import.h
+++ b/source/blender/python/generic/bpy_internal_import.h
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: bpy_internal_import.h 21094 2009-06-23 00:09:26Z gsrb3d $
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
diff --git a/source/blender/python/intern/Makefile b/source/blender/python/intern/Makefile
new file mode 100644
index 00000000000..6c0b7b4d14e
--- /dev/null
+++ b/source/blender/python/intern/Makefile
@@ -0,0 +1,67 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL 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.
+#
+# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+#
+
+LIBNAME = python
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+# OpenGL and Python
+CPPFLAGS += $(OGL_CPPFLAGS)
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
+
+# PreProcessor stuff
+
+CPPFLAGS += -I$(NAN_GHOST)/include
+CPPFLAGS += $(NAN_SDLCFLAGS)
+
+# modules
+CPPFLAGS += -I../../editors/include
+CPPFLAGS += -I../../python
+CPPFLAGS += -I../../makesdna
+CPPFLAGS += -I../../makesrna
+CPPFLAGS += -I../../blenlib
+CPPFLAGS += -I../../blenkernel
+CPPFLAGS += -I../../nodes
+CPPFLAGS += -I../../imbuf
+CPPFLAGS += -I../../blenloader
+CPPFLAGS += -I../../windowmanager
+CPPFLAGS += -I../../render/extern/include
+CPPFLAGS += -I$(NAN_AUDASPACE)/include
+
+# path to the guarded memory allocator
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+CPPFLAGS += -I$(NAN_MEMUTIL)/include
+
+# path to our own headerfiles
+CPPFLAGS += -I..
diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c
index 340e3f4ac57..906f6ccbca2 100644
--- a/source/blender/python/intern/bpy.c
+++ b/source/blender/python/intern/bpy.c
@@ -60,7 +60,7 @@
#include "../generic/blf_py_api.h"
#include "../generic/IDProp.h"
-#include "AUD_PyInit.h"
+//#include "AUD_PyInit.h"
PyObject *bpy_package_py= NULL;
diff --git a/source/blender/python/intern/bpy_operator_wrap.c b/source/blender/python/intern/bpy_operator_wrap.c
index e1ef8aa49c1..de29cb2aeac 100644
--- a/source/blender/python/intern/bpy_operator_wrap.c
+++ b/source/blender/python/intern/bpy_operator_wrap.c
@@ -1,4 +1,3 @@
-
/*
* $Id$
*
diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h
index ba19f155842..e9969277550 100644
--- a/source/blender/python/intern/bpy_rna.h
+++ b/source/blender/python/intern/bpy_rna.h
@@ -31,6 +31,7 @@
/* --- bpy build options --- */
#ifdef WITH_PYTHON_SAFETY
+#include <Python.h>
/* play it safe and keep optional for now, need to test further now this affects looping on 10000's of verts for eg. */
#define USE_WEAKREFS
diff --git a/source/blender/python/intern/bpy_ui.c b/source/blender/python/intern/bpy_ui.c
new file mode 100644
index 00000000000..ab50ebd8bd5
--- /dev/null
+++ b/source/blender/python/intern/bpy_ui.c
@@ -0,0 +1,69 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "bpy_ui.h"
+#include "bpy_util.h"
+#include "bpy_rna.h" /* for rna buttons */
+#include "bpy_operator.h" /* for setting button operator properties */
+
+#include "WM_types.h" /* for WM_OP_INVOKE_DEFAULT & friends */
+
+#include "BLI_dynstr.h"
+
+#include "MEM_guardedalloc.h"
+#include "BKE_global.h" /* evil G.* */
+#include "BKE_context.h"
+
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h" /* only for SpaceLink */
+#include "UI_interface.h"
+#include "WM_api.h"
+
+/* Dummy Module, may want to include non RNA UI functions here, else it can be removed */
+
+static struct PyMethodDef ui_methods[] = {
+ {NULL, NULL, 0, NULL}
+};
+
+static struct PyModuleDef ui_module = {
+ PyModuleDef_HEAD_INIT,
+ "_bpy.ui",
+ "",
+ -1,/* multiple "initialization" just copies the module dict. */
+ ui_methods,
+ NULL, NULL, NULL, NULL
+};
+
+PyObject *BPY_ui_module( void )
+{
+ PyObject *submodule;
+ submodule= PyModule_Create(&ui_module);
+
+ /* INCREF since its its assumed that all these functions return the
+ * module with a new ref like PyDict_New, since they are passed to
+ * PyModule_AddObject which steals a ref */
+ Py_INCREF(submodule);
+
+ return submodule;
+}
diff --git a/source/blender/python/intern/bpy_ui.h b/source/blender/python/intern/bpy_ui.h
new file mode 100644
index 00000000000..95afa1f08c8
--- /dev/null
+++ b/source/blender/python/intern/bpy_ui.h
@@ -0,0 +1,31 @@
+/**
+ * $Id: bpy_ui.h 21094 2009-06-23 00:09:26Z gsrb3d $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef BPY_UI_H__
+#define BPY_UI_H__
+
+#include <Python.h>
+
+PyObject *BPY_ui_module( void );
+
+#endif
diff --git a/source/blender/python/simple_enum_gen.py b/source/blender/python/simple_enum_gen.py
index bc7a2df9fb6..a536f04ecde 100644
--- a/source/blender/python/simple_enum_gen.py
+++ b/source/blender/python/simple_enum_gen.py
@@ -19,24 +19,24 @@
# #**** END GPL LICENSE BLOCK #****
defs = """
- SPACE_EMPTY,
- SPACE_VIEW3D,
- SPACE_IPO,
- SPACE_OUTLINER,
- SPACE_BUTS,
- SPACE_FILE,
+ SPACE_EMPTY,
+ SPACE_VIEW3D,
+ SPACE_IPO,
+ SPACE_OUTLINER,
+ SPACE_BUTS,
+ SPACE_FILE,
SPACE_IMAGE,
- SPACE_INFO,
- SPACE_SEQ,
- SPACE_TEXT,
- SPACE_IMASEL,
- SPACE_SOUND,
- SPACE_ACTION,
- SPACE_NLA,
- SPACE_SCRIPT,
- SPACE_TIME,
- SPACE_NODE,
- SPACEICONMAX
+ SPACE_INFO,
+ SPACE_SEQ,
+ SPACE_TEXT,
+ SPACE_IMASEL,
+ SPACE_SOUND,
+ SPACE_ACTION,
+ SPACE_NLA,
+ SPACE_SCRIPT,
+ SPACE_TIME,
+ SPACE_NODE,
+ SPACEICONMAX
"""
print '\tmod = PyModule_New("dummy");'
@@ -44,21 +44,21 @@ print '\tPyModule_AddObject( submodule, "key", mod );'
for d in defs.split('\n'):
- d = d.replace(',', ' ')
- w = d.split()
+ d = d.replace(',', ' ')
+ w = d.split()
- if not w:
- continue
+ if not w:
+ continue
- try: w.remove("#define")
- except: pass
+ try: w.remove("#define")
+ except: pass
- # print w
+ # print w
- val = w[0]
- py_val = w[0]
+ val = w[0]
+ py_val = w[0]
- print '\tPyModule_AddObject( mod, "%s", PyLong_FromSize_t(%s) );' % (val, py_val)
+ print '\tPyModule_AddObject( mod, "%s", PyLong_FromSize_t(%s) );' % (val, py_val)