diff options
author | Ken Hughes <khughes@pacific.edu> | 2007-03-21 05:23:28 +0300 |
---|---|---|
committer | Ken Hughes <khughes@pacific.edu> | 2007-03-21 05:23:28 +0300 |
commit | 3a834803ef5d74d68d5aa37b9a23f205a473d27f (patch) | |
tree | 10821ce011ca877281ef494dacdcaefde886990b /source/blender/python/api2_2x/Library.c | |
parent | a6db9c59494c1ecf00ba165fff3d9007f0b0fe32 (diff) |
Python API
----------
Support for new bpy.libraries module, which is being proposed to replace
the Blender.Library module.
Diffstat (limited to 'source/blender/python/api2_2x/Library.c')
-rw-r--r-- | source/blender/python/api2_2x/Library.c | 776 |
1 files changed, 759 insertions, 17 deletions
diff --git a/source/blender/python/api2_2x/Library.c b/source/blender/python/api2_2x/Library.c index 4a22540a0ae..4251b83585d 100644 --- a/source/blender/python/api2_2x/Library.c +++ b/source/blender/python/api2_2x/Library.c @@ -28,11 +28,15 @@ * * 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; +} |