Python API
authorKen Hughes <khughes@pacific.edu>
Wed, 21 Mar 2007 02:23:28 +0000 (02:23 +0000)
committerKen Hughes <khughes@pacific.edu>
Wed, 21 Mar 2007 02:23:28 +0000 (02:23 +0000)
----------
Support for new bpy.libraries module, which is being proposed to replace
the Blender.Library module.

13 files changed:
source/blender/blenkernel/BKE_library.h
source/blender/blenkernel/intern/library.c
source/blender/blenloader/BLO_readfile.h
source/blender/blenloader/intern/readfile.c
source/blender/python/BPY_interface.c
source/blender/python/api2_2x/Blender.c
source/blender/python/api2_2x/Library.c
source/blender/python/api2_2x/Library.h [new file with mode: 0644]
source/blender/python/api2_2x/Main.c
source/blender/python/api2_2x/Scene.c
source/blender/python/api2_2x/doc/Bpy.py
source/blender/python/api2_2x/doc/LibData.py [new file with mode: 0644]
source/blender/python/api2_2x/doc/Library.py

index cc6d15f7bcbf964fdf974c8f9baeae31bc0b747b..b0e82a3b7f7bbb39dcf1acd4102794f83bd2992b 100644 (file)
@@ -47,6 +47,7 @@ void *copy_libblock(void *rt);
 void id_lib_extern(struct ID *id);
 void id_us_plus(struct ID *id);
 
+int dup_id(struct ListBase *lb, struct ID *id, const char *name);
 int new_id(struct ListBase *lb, struct ID *id, const char *name);
 
 struct ListBase *wich_libbase(struct Main *mainlib, short type);
index 1dbbe2f92f2c54ab792829ba51b34e729a90c5c5..d8fab3cf6965e05ed4fa9e257fd12da77ff4c57c 100644 (file)
@@ -788,7 +788,7 @@ static void sort_alpha_id(ListBase *lb, ID *id)
        
 }
 
-int new_id(ListBase *lb, ID *id, const char *tname)
+int dup_id(ListBase *lb, ID *id, const char *tname)
 /* only for local blocks: external en indirect blocks already have a unique ID */
 /* return 1: created a new name */
 {
@@ -876,12 +876,21 @@ int new_id(ListBase *lb, ID *id, const char *tname)
                /* this format specifier is from hell... */
                sprintf(id->name+2, "%s.%.3d", left, nr);
        }
-       
-       sort_alpha_id(lb, id);  
-
        return 1;
 }
 
+int new_id(ListBase *lb, ID *id, const char *tname)
+/* only for local blocks: external en indirect blocks already have a unique ID */
+/* return 1: created a new name */
+{
+       int result = dup_id( lb, id, tname );
+
+       if( result )
+               sort_alpha_id(lb, id);  
+
+       return result;
+}
+
 // next to indirect usage in read/writefile also in editobject.c scene.c
 void clear_id_newpoins()
 {
index 2d1a8b7db055045be90189b7e3c4a26d67b33117..7f621410a4faa443d5336706c92788c17a5f51f1 100644 (file)
@@ -219,7 +219,7 @@ BLO_blendhandle_close(
 char *BLO_gethome(void);
 int BLO_has_bfile_extension(char *str);
 void BLO_library_append(struct SpaceFile *sfile, char *dir, int idcode);
-void BLO_script_library_append(BlendHandle *bh, char *dir, char *name, int idcode, short flag);
+void BLO_script_library_append(BlendHandle *bh, char *dir, char *name, int idcode, short flag, struct Scene *scene);
 
 BlendFileData* blo_read_blendafterruntime(int file, int actualsize, BlendReadError *error_r);
 
index dd4ba03aa100b5c9ba6a89c3a2e8b83885e5b838..9aebcd7511630eb232497dcc9ce20736df3a1cc2 100644 (file)
@@ -7282,7 +7282,7 @@ static void append_id_part(FileData *fd, Main *mainvar, ID *id, ID **id_r)
 
 /* common routine to append/link something from a library */
 
-static void library_append( SpaceFile *sfile, char *dir, int idcode,
+static void library_append( Scene *scene, SpaceFile *sfile, char *dir, int idcode,
                int totsel, FileData *fd)
 {
        Main *mainl;
@@ -7299,13 +7299,13 @@ static void library_append( SpaceFile *sfile, char *dir, int idcode,
        curlib= mainl->curlib;
        
        if(totsel==0) {
-               append_named_part(fd, mainl, G.scene, sfile->file, idcode, sfile->flag);
+               append_named_part(fd, mainl, scene, sfile->file, idcode, sfile->flag);
        }
        else {
                int a;
                for(a=0; a<sfile->totfile; a++) {
                        if(sfile->filelist[a].flags & ACTIVE) {
-                               append_named_part(fd, mainl, G.scene, sfile->filelist[a].relname, idcode, sfile->flag);
+                               append_named_part(fd, mainl, scene, sfile->filelist[a].relname, idcode, sfile->flag);
                        }
                }
        }
@@ -7333,9 +7333,9 @@ static void library_append( SpaceFile *sfile, char *dir, int idcode,
 
        /* give a base to loose objects. If group append, do it for objects too */
        if(idcode==ID_GR)
-               give_base_to_objects(G.scene, &(G.main->object), (sfile->flag & FILE_LINK)?NULL:curlib);
+               give_base_to_objects(scene, &(G.main->object), (sfile->flag & FILE_LINK)?NULL:curlib);
        else
-               give_base_to_objects(G.scene, &(G.main->object), NULL);
+               give_base_to_objects(scene, &(G.main->object), NULL);
        
        /* has been removed... erm, why? s..ton) */
        /* 20040907: looks like they are give base already in append_named_part(); -Nathan L */
@@ -7353,7 +7353,8 @@ static void library_append( SpaceFile *sfile, char *dir, int idcode,
 /* append to G.scene */
 /* this should probably be moved into the Python code anyway */
 
-void BLO_script_library_append(BlendHandle *bh, char *dir, char *name, int idcode, short flag)
+void BLO_script_library_append(BlendHandle *bh, char *dir, char *name, 
+               int idcode, short flag, Scene *scene )
 {
        SpaceFile sfile;
 
@@ -7364,7 +7365,7 @@ void BLO_script_library_append(BlendHandle *bh, char *dir, char *name, int idcod
 
        /* try to append the requested object */
 
-       library_append( &sfile, dir, idcode, 0, (FileData *)bh );
+       library_append( scene, &sfile, dir, idcode, 0, (FileData *)bh );
 
        /* do we need to do this? */
        DAG_scene_sort(G.scene);
@@ -7407,7 +7408,7 @@ void BLO_library_append(SpaceFile *sfile, char *dir, int idcode)
        
        if(sfile->flag & FILE_AUTOSELECT) scene_deselect_all(G.scene);
 
-       library_append( sfile, dir, idcode, totsel, fd );
+       library_append( G.scene, sfile, dir, idcode, totsel, fd );
 
        /* when not linking (appending)... */
        if((sfile->flag & FILE_LINK)==0) {
index c8173866f97c204c0e696e517fefb60e9b45846e..3b54033d897f2416b2a664d8c0c1ac18b04ce3ba 100644 (file)
@@ -159,6 +159,7 @@ void BPY_start_python( int argc, char **argv )
        static int argc_copy = 0;
        static char **argv_copy = NULL;
        int first_time = argc;
+       char *str, version[16];
 
        /* we keep a copy of the values of argc and argv so that the game engine
         * can call BPY_start_python(0, NULL) whenever a game ends, without having
@@ -178,8 +179,8 @@ void BPY_start_python( int argc, char **argv )
         * print an error if not found.  See init_syspath() for the
         * rest of our init msgs.
         */
-       // Py_GetVersion() returns a ptr to astatic string
-       printf( "Compiled with Python version %.5s.\n", Py_GetVersion() );
+
+       printf( "Compiled with Python version %s.\n", PY_VERSION );
 
        //Initialize the TOP-LEVEL modules
        PyImport_ExtendInittab(BPy_Inittab_Modules);
index 324975fb73955721870a678ff29f0b2dd8235bf7..165b242fc04e9b1b006c4687d6fe06fc1207b253 100644 (file)
@@ -964,7 +964,7 @@ void M_Blender_Init(void)
        PyDict_SetItemString(dict, "Key", Key_Init());
        PyDict_SetItemString(dict, "Lamp", Lamp_Init());
        PyDict_SetItemString(dict, "Lattice", Lattice_Init());
-       PyDict_SetItemString(dict, "Library", Library_Init());
+       PyDict_SetItemString(dict, "Library", oldLibrary_Init());
        PyDict_SetItemString(dict, "Material", Material_Init());
        PyDict_SetItemString(dict, "Mesh", Mesh_Init()); 
        PyDict_SetItemString(dict, "Metaball", Metaball_Init());
index 4a22540a0ae3534dbe54d72b8998dc402b826259..4251b83585d385fff7079f4724033c4f9dc9e78e 100644 (file)
  *
  * This is a new part of Blender.
  *
- * Contributor(s): Willian P. Germano
+ * Contributor(s): Willian P. Germano, Campbell Barton, Ken Hughes
  *
  * ***** END GPL/BL DUAL LICENSE BLOCK *****
 */
 
+/************************************************************/
+/* Original library module code                             */
+/************************************************************/
+
 #include <Python.h>
 
 #include "DNA_curve_types.h"
@@ -64,14 +68,13 @@ static PyObject *M_Library_Close( PyObject * self );
 static PyObject *M_Library_GetName( PyObject * self );
 static PyObject *M_Library_Update( PyObject * self );
 static PyObject *M_Library_Datablocks( PyObject * self, PyObject * args );
-static PyObject *M_Library_Load( PyObject * self, PyObject * args );
+static PyObject *oldM_Library_Load( PyObject * self, PyObject * args );
 static PyObject *M_Library_LinkableGroups( PyObject * self );
 static PyObject *M_Library_LinkedLibs( PyObject * self );
 
 PyObject *Library_Init( void );
 void EXPP_Library_Close( void );
 
-
 /**
  * Module doc strings.
  */
@@ -119,7 +122,7 @@ static char Library_LinkedLibs_doc[] =
 /**
  * Python method structure definition for Blender.Library submodule.
  */
-struct PyMethodDef M_Library_methods[] = {
+struct PyMethodDef oldM_Library_methods[] = {
        {"Open", M_Library_Open, METH_VARARGS, Library_Open_doc},
        {"Close", ( PyCFunction ) M_Library_Close, METH_NOARGS,
         Library_Close_doc},
@@ -129,7 +132,7 @@ struct PyMethodDef M_Library_methods[] = {
         Library_Update_doc},
        {"Datablocks", M_Library_Datablocks, METH_VARARGS,
         Library_Datablocks_doc},
-       {"Load", M_Library_Load, METH_VARARGS, Library_Load_doc},
+       {"Load", oldM_Library_Load, METH_VARARGS, Library_Load_doc},
        {"LinkableGroups", ( PyCFunction ) M_Library_LinkableGroups,
         METH_NOARGS, Library_LinkableGroups_doc},
        {"LinkedLibs", ( PyCFunction ) M_Library_LinkedLibs,
@@ -144,7 +147,7 @@ struct PyMethodDef M_Library_methods[] = {
  * Only one can be open at a time, so this function also closes
  * the previously opened file, if any.
  */
-PyObject *M_Library_Open( PyObject * self, PyObject * args )
+static PyObject *M_Library_Open( PyObject * self, PyObject * args )
 {
        char *fname = NULL;
        char filename[FILE_MAXDIR+FILE_MAXFILE];
@@ -193,7 +196,7 @@ PyObject *M_Library_Open( PyObject * self, PyObject * args )
 /**
  * Close the current .blend file, if any.
  */
-PyObject *M_Library_Close( PyObject * self )
+static PyObject *M_Library_Close( PyObject * self )
 {
        if( bpy_openlib ) {
                BLO_blendhandle_close( bpy_openlib );
@@ -228,7 +231,7 @@ void EXPP_Library_Close( void )
 /**
  * Get the filename of the currently open library file, if any.
  */
-PyObject *M_Library_GetName( PyObject * self )
+static PyObject *M_Library_GetName( PyObject * self )
 {
        if( bpy_openlib && bpy_openlibname )
                return Py_BuildValue( "s", bpy_openlibname );
@@ -241,7 +244,7 @@ PyObject *M_Library_GetName( PyObject * self )
  * Return a list with all items of a given datablock type
  * (like 'Object', 'Mesh', etc.) in the open library file.
  */
-PyObject *M_Library_Datablocks( PyObject * self, PyObject * args )
+static PyObject *M_Library_Datablocks( PyObject * self, PyObject * args )
 {
        char *name = NULL;
        int blocktype = 0;
@@ -288,7 +291,7 @@ PyObject *M_Library_Datablocks( PyObject * self, PyObject * args )
  * Return a list with the names of all linkable groups in the
  * open library file.
  */
-PyObject *M_Library_LinkableGroups( PyObject * self )
+static PyObject *M_Library_LinkableGroups( PyObject * self )
 {
        LinkNode *l = NULL, *names = NULL;
        PyObject *list = NULL;
@@ -317,7 +320,7 @@ PyObject *M_Library_LinkableGroups( PyObject * self )
 /**
  * Return a list with the names of all externally linked libs used in the current Blend file
  */
-PyObject *M_Library_LinkedLibs( PyObject * self )
+static PyObject *M_Library_LinkedLibs( PyObject * self )
 {
        int counter = 0;
        Library *li;
@@ -335,7 +338,7 @@ PyObject *M_Library_LinkedLibs( PyObject * self )
  * Load (append) a given datablock of a given datablock type
  * to the current scene.
  */
-PyObject *M_Library_Load( PyObject * self, PyObject * args )
+static PyObject *oldM_Library_Load( PyObject * self, PyObject * args )
 {
        char *name = NULL;
        char *base = NULL;
@@ -360,9 +363,9 @@ PyObject *M_Library_Load( PyObject * self, PyObject * args )
                                              "no such Blender datablock type" );
        
        if (linked)
-               BLO_script_library_append( bpy_openlib, bpy_openlibname, name, blocktype, FILE_LINK);
+               BLO_script_library_append( bpy_openlib, bpy_openlibname, name, blocktype, FILE_LINK, G.scene);
        else
-               BLO_script_library_append( bpy_openlib, bpy_openlibname, name, blocktype, 0);
+               BLO_script_library_append( bpy_openlib, bpy_openlibname, name, blocktype, 0, G.scene);
        
        if( update ) {
                M_Library_Update( self );
@@ -394,7 +397,7 @@ PyObject *M_Library_Load( PyObject * self, PyObject * args )
 /**
  * Update all links and remake displists.
  */
-PyObject *M_Library_Update( PyObject * self )
+static PyObject *M_Library_Update( PyObject * self )
 {                              /* code adapted from do_library_append in src/filesel.c: */
        Library *lib = NULL;
 
@@ -425,12 +428,751 @@ PyObject *M_Library_Update( PyObject * self )
  * Called by Blender_Init in Blender.c .
  * @return the registered submodule.
  */
-PyObject *Library_Init( void )
+PyObject *oldLibrary_Init( void )
 {
        PyObject *submod;
 
-       submod = Py_InitModule3( "Blender.Library", M_Library_methods,
+       submod = Py_InitModule3( "Blender.Library", oldM_Library_methods,
                                 M_Library_doc );
 
        return submod;
 }
+
+/************************************************************/
+/* New library (LibData) module code                        */
+/************************************************************/
+
+#include "Library.h"
+
+/* if this module supercedes the old library module, include these instead */
+#if 0
+#include "BLI_blenlib.h"
+#include "MEM_guardedalloc.h"
+
+#include "DNA_curve_types.h"
+#include "DNA_object_types.h"
+#include "DNA_space_types.h" /* for line linked */
+#include "BKE_library.h"       /* for all_local */
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BLO_readfile.h"
+#include "BLI_linklist.h"
+
+#include "Object.h"
+#include "gen_utils.h"
+#endif
+
+#include "gen_library.h"
+
+/* Helper function */
+
+/*
+ * Try to open a library, set Python exceptions as necessary if not
+ * successful.  On success, return a valid handle; othewise return NULL.
+ */
+
+static BlendHandle *open_library( char *filename, char *longFilename )
+{
+       char globalFilename[FILE_MAX];
+       BlendHandle *openlib = NULL;
+
+       /* get complete file name if necessary */
+       BLI_strncpy( longFilename, filename, FILE_MAX ); 
+       BLI_convertstringcode( longFilename, G.sce, 0 );
+
+       /* throw exceptions for wrong file type, cyclic reference */
+       if( !BLO_has_bfile_extension(longFilename) ) {
+               PyErr_SetString( PyExc_ValueError, "file not a library" );
+               return NULL;
+       }
+       if( BLI_streq(G.main->name, longFilename) ) {
+               PyErr_SetString( PyExc_ValueError,
+                               "cannot use current file as library" );
+               return NULL;
+       }
+
+       /* G.sce = last file loaded, save for UI and restore after opening file */
+       BLI_strncpy(globalFilename, G.sce, sizeof(globalFilename));
+       openlib = BLO_blendhandle_from_file( longFilename );
+       BLI_strncpy(G.sce, globalFilename, sizeof(globalFilename)); 
+
+       /* if failed, set that exception code too */
+       if( !openlib )
+               PyErr_SetString( PyExc_IOError, "library not found" );
+
+       return openlib;
+}
+
+/*
+ * Create a specific type of LibraryData object.  These are used for
+ * .append() and .link() access, for iterators, and (for Blender Objects)
+ * for defining "pseudo objects" for scene linking.
+ */
+
+static PyObject *CreatePyObject_LibData( int idtype, int kind,
+               void *name, void *iter, char *filename )
+{
+       BPy_LibraryData *seq = PyObject_NEW( BPy_LibraryData, &LibraryData_Type);
+       seq->iter = iter;               /* the name list (for iterators) */
+       seq->type = idtype;             /* the Blender ID type */
+       seq->kind = kind;               /* used by Blender Objects */
+       seq->name = name;               /* object name, iterator name list, or NULL */
+                                                       /* save the library name */
+       BLI_strncpy( seq->filename, filename, strlen(filename)+1 );
+       return (PyObject *)seq;
+}
+
+/* 
+ * Link/append data to the current .blend file, or create a pseudo object
+ * which can be linked/appended to a scene.
+ */
+
+static PyObject *lib_link_or_append( BPy_LibraryData *self, PyObject * args,
+               int mode )
+{
+       char *name;
+
+       /* get the name of the data used wants to append */
+       if( !PyArg_ParseTuple( args, "s", &name ) )
+               return EXPP_ReturnPyObjError( PyExc_TypeError,
+                       "expected a string" );
+
+       /* 
+        * For everything except objects, just add to Blender's DB.  For objects,
+        * create an APPEND or LINK "pseudo object" for the Scene module.
+        */
+       if( self->type != ID_OB )
+               return LibraryData_importLibData( self, name, 0, NULL );
+       else {
+               /*
+                * If this is already a pseudo object, throw an exception: re-linking
+                * or re-appending is not allowed
+                */
+               if( self->kind != OTHER ) 
+                       return EXPP_ReturnPyObjError( PyExc_ValueError,
+                               "object has already been marked for append or link" );
+
+               /* otherwise, create a pseudo object ready for appending or linking */
+
+               return CreatePyObject_LibData( ID_OB, mode, 
+                               BLI_strdupn( name, strlen( name ) ), NULL, self->filename );
+       }
+}
+
+/*
+ * Perform the actual link or append operation.  This procedure is also
+ * called externally from the Scene module using a "pseudo Object" so we
+ * can be sure objects get linked to a scene.
+ */
+
+PyObject *LibraryData_importLibData( BPy_LibraryData *self, char *name,
+               int mode, Scene *scene )
+{
+       char longFilename[FILE_MAX];
+       char *finalName;
+       BlendHandle *openlib;
+       Library *lib;
+       LinkNode *names, *ptr;
+       ID idtest, *id;
+       ListBase *lb;
+
+       /* try to open the library */
+       openlib = open_library( self->filename, longFilename );
+       if( !openlib )
+               return NULL;
+
+       /* find all datablocks for the specified type */
+       names = BLO_blendhandle_get_datablock_names ( openlib, self->type ); 
+
+       /* now check for a match to the user-specified name */
+       for( ptr = names; ptr; ptr = ptr->next )
+               if( strcmp( ptr->link, name ) == 0 ) break;
+       BLI_linklist_free( names, free );
+
+       /* if no match, throw exception */
+       if( !ptr ) {
+               BLO_blendhandle_close( openlib );
+               return EXPP_ReturnPyObjError( PyExc_ValueError,
+                               "library does not contain specified item" );
+       }
+
+       /*
+        * Figure out what the datablock will be named after it's imported.  If
+        * it's a link, nothing to do.  If it's an append, find what it might
+        * be renamed to.
+        */
+
+       if( mode == FILE_LINK )
+               finalName =  name;
+       else { /* for appends, build a fake ID block, then try to dup it */
+               strncpy( idtest.name+2, name, strlen(name)+1 );
+               *((short *)&idtest.name) = self->type;
+               idtest.newid = NULL;
+               idtest.lib = NULL;
+               dup_id( NULL, &idtest, self->name );
+               finalName = idtest.name+2;
+       }
+
+       /* import from the libary */
+       BLO_script_library_append( openlib, longFilename, name, self->type, mode,
+                       scene );
+
+       /*
+        * locate the library.  If this is an append, make the data local.  If it
+        * is link, we need the library for later
+        */
+       for( lib = G.main->library.first; lib; lib = lib->id.next )
+               if( strcmp( longFilename, lib->name ) == 0 ) {
+                       if( mode != FILE_LINK ) {
+                               all_local( lib );
+                               lib = NULL;
+                       }
+                       break;
+               }
+
+       /* done with library; close it */
+       BLO_blendhandle_close( openlib );
+
+       /* find the base for this type */
+       lb = wich_libbase( G.main, self->type );
+
+       /*
+        * Search the base for the datablock.  For link, lib points to library,
+        * otherwise it's NULL. 
+        */
+       for( id = lb->first; id; id = id->next ) {
+               if( id->lib == lib && id->name[2]==finalName[0] &&
+                               strcmp(id->name+2, finalName)==0 )
+                       return GetPyObjectFromID( id );
+       }
+
+       /* if we get here, something's really wrong */
+       return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+                       "could not find data after reading from library" );
+}
+
+/************************************************************
+ * Python LibraryData_Type getseters
+ ************************************************************/
+
+/* .append(): make a local copy of the library's data (except for objects) */
+
+static PyObject *LibraryData_getAppend( BPy_LibraryData *self, PyObject * args)
+{
+       return lib_link_or_append( self, args, OBJECT_IS_APPEND );
+}
+
+/* .link(): make a link to the library's data (except for objects) */
+
+static PyObject *LibraryData_getLink( BPy_LibraryData *self, PyObject * args)
+{
+       return lib_link_or_append( self, args, OBJECT_IS_LINK );
+}
+
+/************************************************************************
+ * Python LibraryData_Type iterator
+ ************************************************************************/
+
+/* Create and initialize the interator indices */
+
+static PyObject *LibraryData_getIter( BPy_LibraryData * self )
+{
+       char longFilename[FILE_MAX];
+       BlendHandle *openlib;
+       LinkNode *names;
+
+       /* try to open library */
+       openlib = open_library( self->filename, longFilename );
+
+       /* if failed, return exception */
+       if( !openlib )
+               return NULL;
+
+       /* find all datablocks for the specified type */
+       names = BLO_blendhandle_get_datablock_names ( openlib, self->type ); 
+
+       /* close library*/
+       BLO_blendhandle_close( openlib );
+
+       /* build an iterator object for the name list */
+       return CreatePyObject_LibData( self->type, OTHER, names,
+                       names, self->filename );
+}
+
+/* Return next name. */
+
+static PyObject *LibraryData_nextIter( BPy_LibraryData * self )
+{
+       LinkNode *ptr = (LinkNode *)self->iter;
+       PyObject *ob;
+
+       /* if at the end of list, clean up */
+       if( !ptr ) {
+               /* If name list is still allocated, free storage.  This check is
+                * necessary since iter.next() can technically be called repeatedly */
+               if( self->name ) {
+                       BLI_linklist_free( (LinkNode *)self->name, free );
+                       self->name = NULL;
+               }
+               return EXPP_ReturnPyObjError( PyExc_StopIteration,
+                               "iterator at end" );
+       }
+
+       /* otherwise, return the next name in the list */
+       ob = PyString_FromString( ptr->link );
+       ptr = ptr->next;
+       self->iter = ptr;
+       return ob;
+}
+
+/************************************************************************
+ * Python LibraryData_type methods structure
+ ************************************************************************/
+
+static struct PyMethodDef BPy_LibraryData_methods[] = {
+       {"append", (PyCFunction)LibraryData_getAppend, METH_VARARGS,
+        "(str) - create new data from library"},
+       {"link", (PyCFunction)LibraryData_getLink, METH_VARARGS,
+        "(str) - link data from library"},
+       {NULL, NULL, 0, NULL}
+};
+
+/* Deallocate object and its data */
+
+static void LibraryData_dealloc( BPy_LibraryData * self )
+{
+       if( self->name )
+               MEM_freeN( self->name );
+
+       PyObject_DEL( self );
+}
+
+/* Display representation of what Library Data is wrapping */
+
+static PyObject *LibraryData_repr( BPy_LibraryData * self )
+{
+       char *linkstate = "";
+       char *str;
+
+       switch (self->type) {
+       case ID_OB:
+               /* objects can be lib data or pseudo objects */
+               switch( self->kind ) {
+               case OBJECT_IS_APPEND :
+                       linkstate = ", appended";
+                       break;
+               case OBJECT_IS_LINK :
+                       linkstate = ", linked";
+                       break;
+               default:
+                       break;
+               }
+               str = "Object";
+               break;
+       case ID_SCE:
+               str = "Scene";
+               break;
+       case ID_ME:
+               str = "Mesh";
+               break;
+       case ID_CU:
+               str = "Curve";
+               break;
+       case ID_MB:
+               str = "Metaball";
+               break;
+       case ID_MA:
+               str = "Material";
+               break;
+       case ID_TE:
+               str = "Texture";
+               break;
+       case ID_IM: 
+               str = "Image";
+               break;
+       case ID_LT:
+               str = "Lattice";
+               break;
+       case ID_LA:
+               str = "Lamp";
+               break;
+       case ID_CA:
+               str = "Camera";
+               break;
+       case ID_IP:
+               str = "Ipo";
+               break;
+       case ID_WO:
+               str = "World";
+               break;
+       case ID_VF:
+               str = "Font";
+               break;
+       case ID_TXT:
+               str = "Text";
+               break;
+       case ID_SO:
+               str = "Sound";
+               break;
+       case ID_GR:     
+               str = "Group";
+               break;
+       case ID_AR:
+               str = "Armature";
+               break;
+       case ID_AC:
+               str = "Action";
+               break;
+       default:
+               return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+                               "unsupported ID type" );
+       }
+
+       return PyString_FromFormat( "[Library Data (%s%s)]", str, linkstate );
+}
+
+PyTypeObject LibraryData_Type = {
+       PyObject_HEAD_INIT( NULL )  /* required py macro */
+       0,                          /* ob_size */
+       /*  For printing, in format "<module>.<name>" */
+       "Blender LibData",          /* char *tp_name; */
+       sizeof( BPy_LibraryData ),  /* int tp_basicsize; */
+       0,                          /* tp_itemsize;  For allocation */
+
+       /* Methods to implement standard operations */
+
+       ( destructor ) LibraryData_dealloc,/* destructor tp_dealloc; */
+       NULL,                       /* printfunc tp_print; */
+       NULL,                       /* getattrfunc tp_getattr; */
+       NULL,                       /* setattrfunc tp_setattr; */
+       ( cmpfunc ) NULL,           /* cmpfunc tp_compare; */
+       ( reprfunc ) LibraryData_repr, /* reprfunc tp_repr; */
+
+       /* Method suites for standard classes */
+
+       NULL,                       /* PyNumberMethods *tp_as_number; */
+       NULL,                       /* PySequenceMethods *tp_as_sequence; */
+       NULL,                       /* PyMappingMethods *tp_as_mapping; */
+
+       /* More standard operations (here for binary compatibility) */
+
+       NULL,                       /* hashfunc tp_hash; */
+       NULL,                       /* ternaryfunc tp_call; */
+       NULL,                       /* reprfunc tp_str; */
+       NULL,                       /* getattrofunc tp_getattro; */
+       NULL,                       /* setattrofunc tp_setattro; */
+
+       /* Functions to access object as input/output buffer */
+       NULL,                       /* PyBufferProcs *tp_as_buffer; */
+
+  /*** Flags to define presence of optional/expanded features ***/
+       Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
+
+       NULL,                       /*  char *tp_doc;  Documentation string */
+  /*** Assigned meaning in release 2.0 ***/
+       /* call function for all accessible objects */
+       NULL,                       /* traverseproc tp_traverse; */
+
+       /* delete references to contained objects */
+       NULL,                       /* inquiry tp_clear; */
+
+  /***  Assigned meaning in release 2.1 ***/
+  /*** rich comparisons ***/
+       NULL,                       /* richcmpfunc tp_richcompare; */
+
+  /***  weak reference enabler ***/
+       0,                          /* long tp_weaklistoffset; */
+
+  /*** Added in release 2.2 ***/
+       /*   Iterators */
+       (getiterfunc)LibraryData_getIter, /* getiterfunc tp_iter; */
+       (iternextfunc)LibraryData_nextIter, /* iternextfunc tp_iternext; */
+
+  /*** Attribute descriptor and subclassing stuff ***/
+       BPy_LibraryData_methods,    /* struct PyMethodDef *tp_methods; */
+       NULL,                       /* struct PyMemberDef *tp_members; */
+       NULL,                       /* struct PyGetSetDef *tp_getset; */
+       NULL,                       /* struct _typeobject *tp_base; */
+       NULL,                       /* PyObject *tp_dict; */
+       NULL,                       /* descrgetfunc tp_descr_get; */
+       NULL,                       /* descrsetfunc tp_descr_set; */
+       0,                          /* long tp_dictoffset; */
+       NULL,                       /* initproc tp_init; */
+       NULL,                       /* allocfunc tp_alloc; */
+       NULL,                       /* newfunc tp_new; */
+       /*  Low-level free-memory routine */
+       NULL,                       /* freefunc tp_free;  */
+       /* For PyObject_IS_GC */
+       NULL,                       /* inquiry tp_is_gc;  */
+       NULL,                       /* PyObject *tp_bases; */
+       /* method resolution order */
+       NULL,                       /* PyObject *tp_mro;  */
+       NULL,                       /* PyObject *tp_cache; */
+       NULL,                       /* PyObject *tp_subclasses; */
+       NULL,                       /* PyObject *tp_weaklist; */
+       NULL
+};
+
+/*
+ * Create a LibraryData object for a specific type of Blender Group (ID_OB,
+ * ID_MA, etc).  These can then be used to link or append the data.
+ */
+
+static PyObject *LibraryData_CreatePyObject( BPy_Library *self, void *mode )
+{
+       return CreatePyObject_LibData( (int)mode, OTHER, NULL, NULL,
+                       self->filename );
+}
+
+/************************************************************
+ * Python Library_Type getseters
+ ************************************************************/
+
+/*
+ * Return the library's filename.
+ */
+
+static PyObject *Library_getFilename( BPy_Library * self )
+{
+       return PyString_FromString( self->filename );
+}
+
+/*
+ * Set/change the library's filename.
+ */
+
+static int Library_setFilename( BPy_Library * self, PyObject * args )
+{
+       char *filename = PyString_AsString( args );
+       if( !filename )
+               return EXPP_ReturnIntError( PyExc_TypeError, "expected a string" );
+
+       BLI_strncpy( self->filename, filename, sizeof(self->filename) );
+       return 0;
+}
+
+/************************************************************************
+ * Python Library_type attributes get/set structure
+ ************************************************************************/
+
+static PyGetSetDef Library_getseters[] = {
+       {"filename",
+        (getter)Library_getFilename, (setter)Library_setFilename,
+        "library filename",
+        NULL},
+       {"objects",
+        (getter)LibraryData_CreatePyObject, (setter)NULL,
+        "objects from the library",
+        (void *)ID_OB},
+       {"scenes",
+        (getter)LibraryData_CreatePyObject, (setter)NULL,
+        "scenes from the library",
+        (void *)ID_SCE},
+       {"meshes",
+        (getter)LibraryData_CreatePyObject, (setter)NULL,
+        "meshes from the library",
+        (void *)ID_ME},
+       {"curves",
+        (getter)LibraryData_CreatePyObject, (setter)NULL,
+        "curves from the library",
+        (void *)ID_CU},
+       {"metaballs",
+        (getter)LibraryData_CreatePyObject, (setter)NULL,
+        "metaballs from the library",
+        (void *)ID_MB},
+       {"lattices",
+        (getter)LibraryData_CreatePyObject, (setter)NULL,
+        "lattices from the library",
+        (void *)ID_LT},
+       {"lamps",
+        (getter)LibraryData_CreatePyObject, (setter)NULL,
+        "lamps from the library",
+        (void *)ID_LA},
+       {"cameras",
+        (getter)LibraryData_CreatePyObject, (setter)NULL,
+        "cameras from the library",
+        (void *)ID_CA},
+       {"materials",
+        (getter)LibraryData_CreatePyObject, (setter)NULL,
+        "objects from the library",
+        (void *)ID_MA},
+       {"textures",
+        (getter)LibraryData_CreatePyObject, (setter)NULL,
+        "textures from the library",
+        (void *)ID_TE},
+       {"images",
+        (getter)LibraryData_CreatePyObject, (setter)NULL,
+        "images from the library",
+        (void *)ID_IM},
+       {"ipos",
+        (getter)LibraryData_CreatePyObject, (setter)NULL,
+        "ipos from the library",
+        (void *)ID_IP},
+       {"worlds",
+        (getter)LibraryData_CreatePyObject, (setter)NULL,
+        "worlds from the library",
+        (void *)ID_WO},
+       {"fonts",
+        (getter)LibraryData_CreatePyObject, (setter)NULL,
+        "fonts from the library",
+        (void *)ID_VF},
+       {"texts",
+        (getter)LibraryData_CreatePyObject, (setter)NULL,
+        "texts from the library",
+        (void *)ID_TXT},
+       {"groups",
+        (getter)LibraryData_CreatePyObject, (setter)NULL,
+        "groups from the library",
+        (void *)ID_GR},
+       {"sounds",
+        (getter)LibraryData_CreatePyObject, (setter)NULL,
+        "sounds from the library",
+        (void *)ID_SO},
+       {"actions",
+        (getter)LibraryData_CreatePyObject, (setter)NULL,
+        "actions from the library",
+        (void *)ID_AC},
+       {"armatures",
+        (getter)LibraryData_CreatePyObject, (setter)NULL,
+        "armatures from the library",
+        (void *)ID_AR},
+       {NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
+};
+
+/*
+ * Define a new library and create a library object.  We don't actually test
+ * if the library is valid here since we have to do it when the file is
+ * actually accessed later. 
+ */
+
+static PyObject *M_Library_Load(PyObject *self, PyObject * args)
+{
+       char *filename;
+       BPy_Library *lib;
+
+       if( !PyArg_ParseTuple( args, "s", &filename ) )
+               return EXPP_ReturnPyObjError( PyExc_TypeError,
+                       "expected a string" );
+
+       /* try to create a new object */
+       lib = (BPy_Library *)PyObject_NEW( BPy_Library, &Library_Type );
+       if( !lib )
+               return NULL;
+
+       /* assign the library filename for future use, then return */
+       BLI_strncpy( lib->filename, filename, sizeof(lib->filename) );
+
+       return (PyObject *)lib;
+}
+
+static struct PyMethodDef M_Library_methods[] = {
+       {"load", (PyCFunction)M_Library_Load, METH_VARARGS,
+       "(string) - declare a .blend file for use as a library"},
+       {NULL, NULL, 0, NULL}
+};
+
+/*****************************************************************************/
+/* Python Library_Type structure definition:                               */
+/*****************************************************************************/
+PyTypeObject Library_Type = {
+       PyObject_HEAD_INIT( NULL )  /* required py macro */
+       0,                          /* ob_size */
+       /*  For printing, in format "<module>.<name>" */
+       "Blender Library",          /* char *tp_name; */
+       sizeof( BPy_Library ),      /* int tp_basicsize; */
+       0,                          /* tp_itemsize;  For allocation */
+
+       /* Methods to implement standard operations */
+
+       NULL,                       /* destructor tp_dealloc; */
+       NULL,                       /* printfunc tp_print; */
+       NULL,                       /* getattrfunc tp_getattr; */
+       NULL,                       /* setattrfunc tp_setattr; */
+       ( cmpfunc ) NULL,           /* cmpfunc tp_compare; */
+       ( reprfunc ) NULL,          /* reprfunc tp_repr; */
+
+       /* Method suites for standard classes */
+
+       NULL,                       /* PyNumberMethods *tp_as_number; */
+       NULL,                       /* PySequenceMethods *tp_as_sequence; */
+       NULL,                       /* PyMappingMethods *tp_as_mapping; */
+
+       /* More standard operations (here for binary compatibility) */
+
+       NULL,                       /* hashfunc tp_hash; */
+       NULL,                       /* ternaryfunc tp_call; */
+       NULL,                       /* reprfunc tp_str; */
+       NULL,                       /* getattrofunc tp_getattro; */
+       NULL,                       /* setattrofunc tp_setattro; */
+
+       /* Functions to access object as input/output buffer */
+       NULL,                       /* PyBufferProcs *tp_as_buffer; */
+
+  /*** Flags to define presence of optional/expanded features ***/
+       Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
+
+       NULL,                       /*  char *tp_doc;  Documentation string */
+  /*** Assigned meaning in release 2.0 ***/
+       /* call function for all accessible objects */
+       NULL,                       /* traverseproc tp_traverse; */
+
+       /* delete references to contained objects */
+       NULL,                       /* inquiry tp_clear; */
+
+  /***  Assigned meaning in release 2.1 ***/
+  /*** rich comparisons ***/
+       NULL,                       /* richcmpfunc tp_richcompare; */
+
+  /***  weak reference enabler ***/
+       0,                          /* long tp_weaklistoffset; */
+
+  /*** Added in release 2.2 ***/
+       /*   Iterators */
+       NULL,                       /* getiterfunc tp_iter; */
+       NULL,                       /* iternextfunc tp_iternext; */
+
+  /*** Attribute descriptor and subclassing stuff ***/
+       NULL,                       /* struct PyMethodDef *tp_methods; */
+       NULL,                       /* struct PyMemberDef *tp_members; */
+       Library_getseters,          /* struct PyGetSetDef *tp_getset; */
+       NULL,                       /* struct _typeobject *tp_base; */
+       NULL,                       /* PyObject *tp_dict; */
+       NULL,                       /* descrgetfunc tp_descr_get; */
+       NULL,                       /* descrsetfunc tp_descr_set; */
+       0,                          /* long tp_dictoffset; */
+       NULL,                       /* initproc tp_init; */
+       NULL,                       /* allocfunc tp_alloc; */
+       NULL,                       /* newfunc tp_new; */
+       /*  Low-level free-memory routine */
+       NULL,                       /* freefunc tp_free;  */
+       /* For PyObject_IS_GC */
+       NULL,                       /* inquiry tp_is_gc;  */
+       NULL,                       /* PyObject *tp_bases; */
+       /* method resolution order */
+       NULL,                       /* PyObject *tp_mro;  */
+       NULL,                       /* PyObject *tp_cache; */
+       NULL,                       /* PyObject *tp_subclasses; */
+       NULL,                       /* PyObject *tp_weaklist; */
+       NULL
+};
+
+/*
+ * Library module initialization
+ */
+
+static char M_newLibrary_doc[] = "The Blender.lib submodule";
+
+PyObject *Library_Init( void )
+{
+       PyObject *submodule;
+
+       if( PyType_Ready( &Library_Type ) < 0 )
+               return NULL;
+       if( PyType_Ready( &LibraryData_Type ) < 0 )
+               return NULL;
+
+       submodule = Py_InitModule3( "Blender.lib", M_Library_methods,
+                       M_newLibrary_doc );
+       return submodule;
+}
diff --git a/source/blender/python/api2_2x/Library.h b/source/blender/python/api2_2x/Library.h
new file mode 100644 (file)
index 0000000..28d4c34
--- /dev/null
@@ -0,0 +1,76 @@
+/* 
+ * $Id$
+ *
+ * ***** 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): Ken Hughes
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+*/
+
+#ifndef EXPP_LIBRARY_H
+#define EXPP_LIBRARY_H
+
+#include <Python.h>
+#include "DNA_scene_types.h"
+#include "BLI_linklist.h"
+
+#include "blendef.h"
+
+/*****************************************************************************/
+/* Python BPy_Library structure definition:        */
+/*****************************************************************************/
+typedef struct {
+       PyObject_HEAD 
+       char filename[FILE_MAXDIR + FILE_MAXFILE];
+} BPy_Library;
+
+typedef struct {
+       PyObject_HEAD 
+       LinkNode *iter;
+       int type;
+       char filename[FILE_MAXDIR + FILE_MAXFILE];
+       char *name;
+       enum {
+               OBJECT_IS_LINK,
+               OBJECT_IS_APPEND,
+               OTHER
+       } kind;
+} BPy_LibraryData;
+
+extern PyTypeObject Library_Type;
+extern PyTypeObject LibraryData_Type;
+
+#define BPy_LibraryData_Check(v)       ((v)->ob_type == &LibraryData_Type)
+#define BPy_Library_Check(v)       ((v)->ob_type == &Library_Type)
+
+/*****************************************************************************/
+/* Module Blender.Library - public functions    */
+/*****************************************************************************/
+PyObject *Library_Init( void );
+PyObject *LibraryData_importLibData( BPy_LibraryData *self, char *name,
+               int mode, Scene *scene );
+
+#endif                         /* EXPP_LIBRARY_H */
index 4eddea59ab0f27fc65a6eb5aad4aa20f0fe4eb59..ef0804a9bb4d4e71b182b3d51ecdeb798d6b0a69 100644 (file)
 #include "NLA.h"
 #include "Main.h"
 #include "Scene.h"
-
+#include "Library.h"
 
 #include "Config.h" /* config pydata */
 
@@ -746,6 +746,8 @@ static char M_Main_doc[] = "The Blender.Main submodule";
 PyObject *Main_Init( void )
 {
        PyObject *submodule;
+       PyObject *dict;
+
 
        if( PyType_Ready( &MainSeq_Type ) < 0 )
                return NULL;
@@ -753,6 +755,10 @@ PyObject *Main_Init( void )
                return NULL;    
        
        submodule = Py_InitModule3( "Blender.Main", NULL, M_Main_doc );
+       dict = PyModule_GetDict( submodule );
+
+       PyDict_SetItemString( dict, "libraries", Library_Init(  ) );
+
        
        /* Python Data Types */
        PyModule_AddObject( submodule, "scenes", MainSeq_CreatePyObject(NULL, ID_SCE) );
index 13258b32f5312794ba6492f53ab6f84f5caf8868..ff0eb3ff20dc07326f7303bd495a2bdc6badf84f 100644 (file)
@@ -72,6 +72,7 @@ struct View3D;
 #include "Metaball.h"
 #include "IDProp.h"
 #include "Text3d.h"
+#include "Library.h"
 
 #include "gen_utils.h"
 #include "gen_library.h"
@@ -1419,6 +1420,13 @@ static PyObject *SceneObSeq_link( BPy_SceneObSeq * self, PyObject *pyobj )
                                              "Cannot modify scene objects while iterating" );
        */
        
+       if( PyTuple_Size(pyobj) == 1 ) {
+               BPy_LibraryData *seq = ( BPy_LibraryData * )PyTuple_GET_ITEM( pyobj, 0 );
+               if( BPy_LibraryData_Check( seq ) )
+                       return LibraryData_importLibData( seq, seq->name,
+                                       ( seq->kind == OBJECT_IS_LINK ? FILE_LINK : 0 ),
+                                       self->bpyscene->scene );
+       }
        return Scene_link(self->bpyscene, pyobj);
 }
 
index b93cf4b100a2d6f7383c9d948263668c0ab842cd..7bf3afe82495d4bfccf7aed4ad961e2f0ae3a16d 100644 (file)
@@ -130,6 +130,8 @@ Example::
 @type armatures: L{dataIterator}
 @var actions: iterator for L{action<NLA.Action>} data
 @type actions: L{dataIterator}
+@var libraries: L{New library<LibData>} submodule
+@type libraries: L{New library<LibData>}
 
 """
 
diff --git a/source/blender/python/api2_2x/doc/LibData.py b/source/blender/python/api2_2x/doc/LibData.py
new file mode 100644 (file)
index 0000000..7884ea5
--- /dev/null
@@ -0,0 +1,137 @@
+# bpy.lib submodule
+
+"""
+The bpy.libraries submodule.
+
+Libraries
+=========
+
+This module provides access to objects stored in .blend files.  With it scripts
+can append from Blender files to the current scene, like the File->Append
+menu entry in Blender does.  It allows programmers to use .blend files as
+data files for their scripts.
+
+@warn: This module is new and being considered as a replacement for the 
+L{original Library<Library>} module.  Users should stay tuned to see
+which module is supported in the end.
+
+Example::
+       import bpy
+
+       scn= bpy.scenes.active                            # get current scene
+       lib = bpy.libraries.load('//file.blend')          # open file.blend
+       ob = scn.objects.link(lib.objects.append('Cube')) # append Cube object from library to current scene
+       mat = lib.objects.link('Material')                # get a link to a material
+       me = ob.getData(mesh=1)                           # get mesh data
+       me.materials[0] = mat                             # assign linked material to mesh
+"""
+
+def load(filename):
+  """
+  Select an existing .blend file for use as a library.  Unlike the 
+  Library module, multiple libraries can be defined at the same time.  
+  
+  @type filename: string
+  @param filename: The filename of a Blender file. Filenames starting with "//" will be loaded relative to the blend file's location.
+  @rtype: Library
+  @return: return a L{Library} object.
+  """
+
+class Libraries:
+       """
+       The Library object
+       ==================
+       This class provides a unified way to access and manipulate library types
+       in Blender.
+       It provides access to scenes, objects, meshes, curves, metaballs,
+       materials, textures, images, lattices, lamps, cameras, ipos, worlds,
+       fonts, texts, sounds, groups, armatures, and actions.
+       @ivar filename: The path to the library
+       @type filename: string
+       @ivar scenes: library L{scene<Scene.Scene>} data
+       @type scenes: L{LibData}
+       @ivar objects: library L{object<Object.Object>} data
+       @type objects: L{LibData}
+       @ivar meshes: library L{mesh<Mesh.Mesh>} data
+       @type meshes: L{LibData}
+       @ivar curves: library L{curve<Curve.Curve>} data
+       @type curves: L{LibData}
+       @ivar metaballs: library L{metaball<Metaball.Metaball>} data
+       @type metaballs: L{LibData}
+       @ivar materials: library L{material<Material.Material>} data
+       @type materials: L{LibData}
+       @ivar textures: library L{texture<Texture.Texture>} data
+       @type textures: L{LibData}
+       @ivar images: library L{image<Image.Image>} data
+       @type images: L{LibData}
+       @ivar lattices: library L{lattice<Lattice.Lattice>} data
+       @type lattices: L{LibData}
+       @ivar lamps: library L{lamp<Lamp.Lamp>} data
+       @type lamps: L{LibData}
+       @ivar cameras: library L{camera<Camera.Camera>} data
+       @type cameras: L{LibData}
+       @ivar ipos: library L{ipo<Ipo.Ipo>} data
+       @type ipos: L{LibData}
+       @ivar worlds: library L{world<World.World>} data
+       @type worlds: L{LibData}
+       @ivar fonts: library L{font<Font.Font>} data
+       @type fonts: L{LibData}
+       @ivar texts: library L{text<Text.Text>} data
+       @type texts: L{LibData}
+       @ivar sounds: library L{sound<Sound.Sound>} data
+       @type sounds: L{LibData}
+       @ivar groups: library L{group<Group.Group>} data
+       @type groups: L{LibData}
+       @ivar armatures: library L{armature<Armature.Armature>} data
+       @type armatures: L{LibData}
+       @ivar actions: library L{action<NLA.Action>} data
+       @type actions: L{LibData}
+       """
+
+class LibData:
+       """
+       Generic Library Data Access
+       ===========================
+       This class provides access to a specific type of library data.
+       """
+
+       def append(name):
+               """
+               Append a new datablock from a library. The new copy
+               is added to the current .blend file.
+
+               B{Note}: Blender Objects cannot be appended or linked without linking
+               them to a scene.  For this reason, lib.objects.append() returns a
+               special "wrapper object" which must be passed to Scene.objects.link()
+               or bpy.scenes.active.link() in order to actually create the object.
+               So the following code will not create a new object::
+                       import bpy
+
+                       scn= bpy.scenes.active                            # get current scene
+                       lib = bpy.libraries.load('//file.blend')          # open file.blend
+                       pseudoOb = lib.objects.append('Cube'))            # get an object wrapper
+               But this code will::
+                       import bpy
+
+                       scn= bpy.scenes.active                            # get current scene
+                       lib = bpy.libraries.load('//file.blend')          # open file.blend
+                       pseudoOb = lib.objects.append('Cube'))            # get an object wrapper
+                       ob = scn.objects.link(pseudoOb)                                   # link to scene
+               @rtype: Blender data
+               @return: return a Blender datablock or object
+               @raise IOError: library cannot be read
+               @raise ValueError: library does not contain B{name}
+               """
+       
+       def link(name):
+               """
+               Link a new datablock from a library.  The linked data is not copied
+               into the local .blend file.
+
+               See L{append} for notes on special handling of Blender Objects.
+               @rtype: Blender data
+               @return: return a Blender datablock or object
+               @raise IOError: library cannot be read
+               @raise ValueError: library does not contain B{name}
+               """
+               
index 840884f1efbc0cff64e47737f3c2800c897efea1..c99739d939b6e26cbcf7843187643dad65ba7639 100644 (file)
@@ -11,7 +11,9 @@ can append from Blender files to the current scene, like the File->Append
 menu entry in Blender does.  It allows programmers to use .blend files as
 data files for their scripts.
 
-@warn: This is a new, still experimental module.
+@warn: This module is being considered for deprecation.  Users should
+consider using the L{new Library<LibData>} module and stay tuned to see
+which module is supported in the end.
 
 Example::
   import Blender