diff options
author | Willian Padovani Germano <wpgermano@gmail.com> | 2005-04-21 23:44:52 +0400 |
---|---|---|
committer | Willian Padovani Germano <wpgermano@gmail.com> | 2005-04-21 23:44:52 +0400 |
commit | 589ce4a005ce16c5a628cd51819e20623a23c891 (patch) | |
tree | 111a9dc91ad3f1843694d47aaf8eb66c1358820d /source/blender/python | |
parent | c5214c15716715cd513e1d2b61433784eb64b617 (diff) |
BPython:
- based on a request by Campbell (he also provided a patch for scene.Layer) access to layers was improved a little, keeping the old method (ob.Layers is a bitmask) and adding the nicer one (ob.layers is a list of ints). Done for objects and scenes. House-cleaning: .Layer was renamed to .Layers (actually just using strncmp instead of strcmp, so both work, same done for Window.ViewLayers).
- finally committing patch by Ken Hughes to let .clearScriptLinks() accept a parameter (list of strings) to clear only specified texts.
- doc updates and fixes (JMS reported a problem in nmesh.transform() example code).
Thanks all who contributed.
Diffstat (limited to 'source/blender/python')
23 files changed, 651 insertions, 347 deletions
diff --git a/source/blender/python/api2_2x/Camera.c b/source/blender/python/api2_2x/Camera.c index a6d06512ecb..b3e71fdda17 100644 --- a/source/blender/python/api2_2x/Camera.c +++ b/source/blender/python/api2_2x/Camera.c @@ -25,7 +25,7 @@ * * This is a new part of Blender. * - * Contributor(s): Willian P. Germano, Johnny Matthews + * Contributor(s): Willian P. Germano, Johnny Matthews, Ken Hughes * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ @@ -125,7 +125,7 @@ static PyObject *Camera_setDrawSize( BPy_Camera * self, PyObject * args ); static PyObject *Camera_setScale( BPy_Camera * self, PyObject * args ); static PyObject *Camera_getScriptLinks( BPy_Camera * self, PyObject * args ); static PyObject *Camera_addScriptLink( BPy_Camera * self, PyObject * args ); -static PyObject *Camera_clearScriptLinks( BPy_Camera * self ); +static PyObject *Camera_clearScriptLinks( BPy_Camera * self, PyObject * args ); static PyObject *Camera_insertIpoKey( BPy_Camera * self, PyObject * args ); Camera *GetCameraByName( char *name ); @@ -187,7 +187,8 @@ static PyMethodDef BPy_Camera_methods[] = { "(evt) string: FrameChanged or Redraw."}, {"clearScriptLinks", ( PyCFunction ) Camera_clearScriptLinks, METH_NOARGS, - "() - Delete all scriptlinks from this camera."}, + "() - Delete all scriptlinks from this camera.\n" + "([s1<,s2,s3...>]) - Delete specified scriptlinks from this camera."}, {NULL, NULL, 0, NULL} }; @@ -784,22 +785,18 @@ static PyObject *Camera_addScriptLink( BPy_Camera * self, PyObject * args ) slink = &( cam )->scriptlink; - if( !EXPP_addScriptLink( slink, args, 0 ) ) - return EXPP_incr_ret( Py_None ); - else - return NULL; + return EXPP_addScriptLink( slink, args, 0 ); } /* cam.clearScriptLinks */ -static PyObject *Camera_clearScriptLinks( BPy_Camera * self ) +static PyObject *Camera_clearScriptLinks( BPy_Camera * self, PyObject * args ) { Camera *cam = self->camera; ScriptLink *slink = NULL; slink = &( cam )->scriptlink; - return EXPP_incr_ret( Py_BuildValue - ( "i", EXPP_clearScriptLinks( slink ) ) ); + return EXPP_clearScriptLinks( slink, args ); } /* cam.getScriptLinks */ diff --git a/source/blender/python/api2_2x/Lamp.c b/source/blender/python/api2_2x/Lamp.c index e34e5bdd83d..b474f7bb7b8 100644 --- a/source/blender/python/api2_2x/Lamp.c +++ b/source/blender/python/api2_2x/Lamp.c @@ -24,7 +24,8 @@ * * This is a new part of Blender. * - * Contributor(s): Willian P. Germano, Nathan Letwory + * Contributor(s): Willian P. Germano, Nathan Letwory, Stephen Swaney, + * Ken Hughes * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ @@ -215,7 +216,7 @@ static PyObject *Lamp_setColorComponent( BPy_Lamp * self, char *key, PyObject * args ); static PyObject *Lamp_getScriptLinks( BPy_Lamp * self, PyObject * args ); static PyObject *Lamp_addScriptLink( BPy_Lamp * self, PyObject * args ); -static PyObject *Lamp_clearScriptLinks( BPy_Lamp * self ); +static PyObject *Lamp_clearScriptLinks( BPy_Lamp * self, PyObject * args ); /*****************************************************************************/ /* Python BPy_Lamp methods table: */ @@ -303,8 +304,9 @@ static PyMethodDef BPy_Lamp_methods[] = { "(text) - string: an existing Blender Text name;\n" "(evt) string: FrameChanged or Redraw."}, {"clearScriptLinks", ( PyCFunction ) Lamp_clearScriptLinks, - METH_NOARGS, - "() - Delete all scriptlinks from this lamp."}, + METH_VARARGS, + "() - Delete all scriptlinks from this lamp.\n" + "([s1<,s2,s3...>]) - Delete specified scriptlinks from this lamp."}, {"getIpo", ( PyCFunction ) Lamp_getIpo, METH_NOARGS, "() - get IPO for this lamp"}, {"clearIpo", ( PyCFunction ) Lamp_clearIpo, METH_NOARGS, @@ -1231,22 +1233,18 @@ static PyObject *Lamp_addScriptLink( BPy_Lamp * self, PyObject * args ) slink = &( lamp )->scriptlink; - if( !EXPP_addScriptLink( slink, args, 0 ) ) - return EXPP_incr_ret( Py_None ); - else - return NULL; + return EXPP_addScriptLink( slink, args, 0 ); } /* lamp.clearScriptLinks */ -static PyObject *Lamp_clearScriptLinks( BPy_Lamp * self ) +static PyObject *Lamp_clearScriptLinks( BPy_Lamp * self, PyObject * args ) { Lamp *lamp = self->lamp; ScriptLink *slink = NULL; slink = &( lamp )->scriptlink; - return EXPP_incr_ret( Py_BuildValue - ( "i", EXPP_clearScriptLinks( slink ) ) ); + return EXPP_clearScriptLinks( slink, args ); } /* mat.getScriptLinks */ diff --git a/source/blender/python/api2_2x/Material.c b/source/blender/python/api2_2x/Material.c index f26c172f889..6d40df057b1 100644 --- a/source/blender/python/api2_2x/Material.c +++ b/source/blender/python/api2_2x/Material.c @@ -26,7 +26,7 @@ * This is a new part of Blender. * * Contributor(s): Willian P. Germano, Michel Selten, Alex Mole, - * Alexander Szakaly, Campbell Barton + * Alexander Szakaly, Campbell Barton, Ken Hughes * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ @@ -487,11 +487,9 @@ static PyObject *Material_clearTexture( BPy_Material * self, PyObject * args ); static PyObject *Material_setColorComponent( BPy_Material * self, char *key, PyObject * args ); -static PyObject *Material_getScriptLinks( BPy_Material * self, - PyObject * args ); -static PyObject *Material_addScriptLink( BPy_Material * self, - PyObject * args ); -static PyObject *Material_clearScriptLinks( BPy_Material * self ); +static PyObject *Material_getScriptLinks(BPy_Material *self, PyObject * args ); +static PyObject *Material_addScriptLink(BPy_Material * self, PyObject * args ); +static PyObject *Material_clearScriptLinks(BPy_Material *self, PyObject *args); static PyObject *Material_insertIpoKey( BPy_Material * self, PyObject * args ); @@ -668,8 +666,9 @@ static PyMethodDef BPy_Material_methods[] = { "(text) - string: an existing Blender Text name;\n" "(evt) string: FrameChanged or Redraw."}, {"clearScriptLinks", ( PyCFunction ) Material_clearScriptLinks, - METH_NOARGS, - "() - Delete all scriptlinks from this material."}, + METH_VARARGS, + "() - Delete all scriptlinks from this material.\n" + "([s1<,s2,s3...>]) - Delete specified scriptlinks from this material."}, {NULL, NULL, 0, NULL} }; @@ -1977,22 +1976,18 @@ static PyObject *Material_addScriptLink( BPy_Material * self, PyObject * args ) slink = &( mat )->scriptlink; - if( !EXPP_addScriptLink( slink, args, 0 ) ) - return EXPP_incr_ret( Py_None ); - else - return NULL; + return EXPP_addScriptLink( slink, args, 0 ); } /* mat.clearScriptLinks */ -static PyObject *Material_clearScriptLinks( BPy_Material * self ) +static PyObject *Material_clearScriptLinks(BPy_Material *self, PyObject *args ) { Material *mat = self->material; ScriptLink *slink = NULL; slink = &( mat )->scriptlink; - return EXPP_incr_ret( Py_BuildValue - ( "i", EXPP_clearScriptLinks( slink ) ) ); + return EXPP_clearScriptLinks( slink, args ); } /* mat.getScriptLinks */ diff --git a/source/blender/python/api2_2x/NMesh.c b/source/blender/python/api2_2x/NMesh.c index 2e6f2ca2601..f0afe5b7b6f 100644 --- a/source/blender/python/api2_2x/NMesh.c +++ b/source/blender/python/api2_2x/NMesh.c @@ -23,7 +23,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. * - * This is a new part of Blender. + * This is a new part of Blender, but it borrows all the old NMesh code. * * Contributor(s): Willian P. Germano, Jordi Rovira i Bonet, Joseph Gilbert, * Bala Gi, Alexander Szakaly, Stephane Soppera, Campbell Barton diff --git a/source/blender/python/api2_2x/Object.c b/source/blender/python/api2_2x/Object.c index 51640704bd4..696a201a3fd 100644 --- a/source/blender/python/api2_2x/Object.c +++ b/source/blender/python/api2_2x/Object.c @@ -29,7 +29,8 @@ * * * Contributor(s): Michel Selten, Willian Germano, Jacques Guignot, - * Joseph Gilbert, Stephen Swaney, Bala Gi, Campbell Barton, Johnny Matthews + * Joseph Gilbert, Stephen Swaney, Bala Gi, Campbell Barton, Johnny Matthews, + * Ken Hughes * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ @@ -184,7 +185,7 @@ static PyObject *Object_copyAllPropertiesTo( BPy_Object * self, PyObject * args ); static PyObject *Object_getScriptLinks( BPy_Object * self, PyObject * args ); static PyObject *Object_addScriptLink( BPy_Object * self, PyObject * args ); -static PyObject *Object_clearScriptLinks( BPy_Object * self ); +static PyObject *Object_clearScriptLinks( BPy_Object * self, PyObject *args ); static PyObject *Object_setDupliVerts ( BPy_Object * self, PyObject * args ); static PyObject *Object_getPIStrength( BPy_Object * self ); static PyObject *Object_setPIStrength( BPy_Object * self, PyObject * args ); @@ -501,8 +502,9 @@ works only if self and the object specified are of the same type."}, "(text) - string: an existing Blender Text name;\n" "(evt) string: FrameChanged or Redraw."}, {"clearScriptLinks", ( PyCFunction ) Object_clearScriptLinks, - METH_NOARGS, - "() - Delete all scriptlinks from this object."}, + METH_VARARGS, + "() - Delete all scriptlinks from this object.\n" + "([s1<,s2,s3...>]) - Delete specified scriptlinks from this object."}, {"setDupliVerts", ( PyCFunction ) Object_setDupliVerts, METH_VARARGS, "() - set or reset duplicate child objects on all vertices"}, {NULL, NULL, 0, NULL} @@ -2256,22 +2258,18 @@ static PyObject *Object_addScriptLink( BPy_Object * self, PyObject * args ) slink = &( obj )->scriptlink; - if( !EXPP_addScriptLink( slink, args, 0 ) ) - return EXPP_incr_ret( Py_None ); - else - return NULL; + return EXPP_addScriptLink( slink, args, 0 ); } /* obj.clearScriptLinks */ -static PyObject *Object_clearScriptLinks( BPy_Object * self ) +static PyObject *Object_clearScriptLinks( BPy_Object * self, PyObject * args ) { Object *obj = self->object; ScriptLink *slink = NULL; slink = &( obj )->scriptlink; - return EXPP_incr_ret( Py_BuildValue - ( "i", EXPP_clearScriptLinks( slink ) ) ); + return EXPP_clearScriptLinks( slink, args ); } /* obj.getScriptLinks */ @@ -2479,8 +2477,31 @@ static PyObject *Object_getAttr( BPy_Object * obj, char *name ) } return ( NULL ); } - if( StringEqual( name, "Layer" ) ) + /* accept both Layer (old, for compatibility) and Layers */ + if( strncmp( name, "Layer", 5 ) == 0) return ( PyInt_FromLong( object->lay ) ); + /* Layers returns a bitmask, layers returns a list of integers */ + if( StringEqual( name, "layers" ) ) { + int layers, bit = 0, val = 0; + PyObject *item = NULL, *laylist = PyList_New( 0 ); + + if( !laylist ) + return ( EXPP_ReturnPyObjError( PyExc_MemoryError, + "couldn't create pylist!" ) ); + + layers = object->lay; + + while( bit < 20 ) { + val = 1 << bit; + if( layers & val ) { + item = Py_BuildValue( "i", bit + 1 ); + PyList_Append( laylist, item ); + Py_DECREF( item ); + } + bit++; + } + return laylist; + } if( StringEqual( name, "parent" ) ) { if( object->parent ) return ( Object_CreatePyObject( object->parent ) ); @@ -2658,7 +2679,8 @@ static int Object_setAttr( BPy_Object * obj, char *name, PyObject * value ) } return ( 0 ); } - if( StringEqual( name, "Layer" ) ) { + /* accept both Layer (for compatibility) and Layers */ + if( strncmp( name, "Layer", 5 ) == 0 ) { /* usage note: caller of this func needs to do a Blender.Redraw(-1) to update and redraw the interface */ @@ -2673,9 +2695,10 @@ static int Object_setAttr( BPy_Object * obj, char *name, PyObject * value ) /* uppper 2 nibbles are for local view */ newLayer &= 0x00FFFFFF; - if( newLayer == 0 ) /* bail if nothing to do */ - return ( 0 ); - + if( newLayer == 0 ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "bitmask must have from 1 up to 20 bits set"); + /* update any bases pointing to our object */ base = FIRSTBASE; /* first base in current scene */ while( base ){ @@ -2690,11 +2713,59 @@ static int Object_setAttr( BPy_Object * obj, char *name, PyObject * value ) return ( 0 ); } + if( StringEqual( name, "layers" ) ) { + /* usage note: caller of this func needs to do a + Blender.Redraw(-1) to update and redraw the interface */ + + Base *base; + int layers = 0, len_list = 0; + int local, i, val; + PyObject *list = NULL, *item = NULL; + + if( !PyArg_Parse( value, "O!", &PyList_Type, &list ) ) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected a list of integers" ); + + len_list = PyList_Size(list); + + if (len_list == 0) + return EXPP_ReturnIntError( PyExc_AttributeError, + "list can't be empty, at least one layer must be set" ); + + for( i = 0; i < len_list; i++ ) { + item = PyList_GetItem( list, i ); + if( !PyInt_Check( item ) ) + return EXPP_ReturnIntError + ( PyExc_AttributeError, + "list must contain only integer numbers" ); + + val = ( int ) PyInt_AsLong( item ); + if( val < 1 || val > 20 ) + return EXPP_ReturnIntError + ( PyExc_AttributeError, + "layer values must be in the range [1, 20]" ); + + layers |= 1 << ( val - 1 ); + } + + /* update any bases pointing to our object */ + base = FIRSTBASE; /* first base in current scene */ + while( base ){ + if( base->object == obj->object ) { + local = base->lay &= 0xFF000000; + base->lay = local | layers; + object->lay = base->lay; + } + base = base->next; + } + countall(); + + return ( 0 ); + } if( StringEqual( name, "parent" ) ) { /* This is not allowed. */ - EXPP_ReturnPyObjError( PyExc_AttributeError, + return EXPP_ReturnIntError( PyExc_AttributeError, "Setting the parent is not allowed." ); - return ( 0 ); } if( StringEqual( name, "track" ) ) { if( Object_makeTrack( obj, valtuple ) != Py_None ) @@ -2704,27 +2775,23 @@ static int Object_setAttr( BPy_Object * obj, char *name, PyObject * value ) } if( StringEqual( name, "data" ) ) { /* This is not allowed. */ - EXPP_ReturnPyObjError( PyExc_AttributeError, + return EXPP_ReturnIntError( PyExc_AttributeError, "Setting the data is not allowed." ); - return ( 0 ); } if( StringEqual( name, "ipo" ) ) { /* This is not allowed. */ - EXPP_ReturnPyObjError( PyExc_AttributeError, + return EXPP_ReturnIntError( PyExc_AttributeError, "Setting the ipo is not allowed." ); - return ( 0 ); } if( StringEqual( name, "mat" ) ) { /* This is not allowed. */ - EXPP_ReturnPyObjError( PyExc_AttributeError, + return EXPP_ReturnIntError( PyExc_AttributeError, "Setting the matrix is not allowed." ); - return ( 0 ); } if( StringEqual( name, "matrix" ) ) { /* This is not allowed. */ - EXPP_ReturnPyObjError( PyExc_AttributeError, + return EXPP_ReturnIntError( PyExc_AttributeError, "Please use .setMatrix(matrix)" ); - return ( 0 ); } if( StringEqual( name, "colbits" ) ) return ( !PyArg_Parse( value, "h", &( object->colbits ) ) ); diff --git a/source/blender/python/api2_2x/Scene.c b/source/blender/python/api2_2x/Scene.c index 426938d8e4a..e3a668fd0a8 100644 --- a/source/blender/python/api2_2x/Scene.c +++ b/source/blender/python/api2_2x/Scene.c @@ -93,6 +93,9 @@ struct PyMethodDef M_Scene_methods[] = { //-----------------------BPy_Scene method declarations-------------------- static PyObject *Scene_getName( BPy_Scene * self ); static PyObject *Scene_setName( BPy_Scene * self, PyObject * arg ); +static PyObject *Scene_getLayers( BPy_Scene * self ); +static PyObject *Scene_setLayers( BPy_Scene * self, PyObject * arg ); +static PyObject *Scene_setLayersMask( BPy_Scene * self, PyObject * arg ); static PyObject *Scene_copy( BPy_Scene * self, PyObject * arg ); static PyObject *Scene_makeCurrent( BPy_Scene * self ); static PyObject *Scene_update( BPy_Scene * self, PyObject * args ); @@ -105,19 +108,9 @@ static PyObject *Scene_getRenderingContext( BPy_Scene * self ); static PyObject *Scene_getRadiosityContext( BPy_Scene * self ); static PyObject *Scene_getScriptLinks( BPy_Scene * self, PyObject * args ); static PyObject *Scene_addScriptLink( BPy_Scene * self, PyObject * args ); -static PyObject *Scene_clearScriptLinks( BPy_Scene * self ); +static PyObject *Scene_clearScriptLinks( BPy_Scene * self, PyObject * args ); static PyObject *Scene_play( BPy_Scene * self, PyObject * args ); -//deprecated methods -static PyObject *Scene_currentFrame( BPy_Scene * self, PyObject * args ); -static PyObject *Scene_getWinSize( BPy_Scene * self ); -static PyObject *Scene_setWinSize( BPy_Scene * self, PyObject * arg ); -static PyObject *Scene_startFrame( BPy_Scene * self, PyObject * args ); -static PyObject *Scene_endFrame( BPy_Scene * self, PyObject * args ); -static PyObject *Scene_frameSettings( BPy_Scene * self, PyObject * args ); -static PyObject *Scene_getRenderdir( BPy_Scene * self ); -static PyObject *Scene_getBackbufdir( BPy_Scene * self ); - //internal static void Scene_dealloc( BPy_Scene * self ); static int Scene_setAttr( BPy_Scene * self, char *name, PyObject * v ); @@ -131,6 +124,11 @@ static PyMethodDef BPy_Scene_methods[] = { "() - Return Scene name"}, {"setName", ( PyCFunction ) Scene_setName, METH_VARARGS, "(str) - Change Scene name"}, + {"getLayers", ( PyCFunction ) Scene_getLayers, METH_NOARGS, + "() - Return a list of layers int indices which are set in this Scene "}, + {"setLayers", ( PyCFunction ) Scene_setLayers, METH_VARARGS, + "(layers) - Change layers which are set in this Scene\n" + "(layers) - list of integers in the range [1, 20]."}, {"copy", ( PyCFunction ) Scene_copy, METH_VARARGS, "(duplicate_objects = 1) - Return a copy of this scene\n" "The optional argument duplicate_objects defines how the scene\n" @@ -160,39 +158,18 @@ static PyMethodDef BPy_Scene_methods[] = { "(text) - string: an existing Blender Text name;\n" "(evt) string: FrameChanged, OnLoad or Redraw."}, {"clearScriptLinks", ( PyCFunction ) Scene_clearScriptLinks, - METH_NOARGS, - "() - Delete all scriptlinks from this scene."}, + METH_VARARGS, + "() - Delete all scriptlinks from this scene.\n" + "([s1<,s2,s3...>]) - Delete specified scriptlinks from this scene."}, {"setCurrentCamera", ( PyCFunction ) Scene_setCurrentCamera, METH_VARARGS, "() - Set the currently active Camera"}, - //DEPRECATED - {"getWinSize", ( PyCFunction ) Scene_getWinSize, METH_NOARGS, - "() - Return Render window [x,y] dimensions"}, - {"setWinSize", ( PyCFunction ) Scene_setWinSize, METH_VARARGS, - "(str) - Change Render window [x,y] dimensions"}, - {"startFrame", ( PyCFunction ) Scene_startFrame, METH_VARARGS, - "(frame) - If frame is given, the start frame is set and" - "\nreturned in any case"}, - {"endFrame", ( PyCFunction ) Scene_endFrame, METH_VARARGS, - "(frame) - If frame is given, the end frame is set and" - "\nreturned in any case"}, - {"frameSettings", ( PyCFunction ) Scene_frameSettings, METH_VARARGS, - "(start, end, current) - Sets or retrieves the Scene's frame" - " settings.\nIf the frame arguments are specified, they are set. " - "A tuple (start, end, current) is returned in any case."}, - {"getRenderdir", ( PyCFunction ) Scene_getRenderdir, METH_NOARGS, - "() - Return directory where rendered images are saved to"}, - {"getBackbufdir", ( PyCFunction ) Scene_getBackbufdir, METH_NOARGS, - "() - Return location of the backbuffer image"}, {"getRenderingContext", ( PyCFunction ) Scene_getRenderingContext, METH_NOARGS, "() - Get the rendering context for the scene and return it as a BPy_RenderData"}, {"getRadiosityContext", ( PyCFunction ) Scene_getRadiosityContext, METH_NOARGS, "() - Get the radiosity context for this scene."}, - {"currentFrame", ( PyCFunction ) Scene_currentFrame, METH_VARARGS, - "(frame) - If frame is given, the current frame is set and" - "\nreturned in any case"}, {"play", ( PyCFunction ) Scene_play, METH_VARARGS, "(mode = 0, win = VIEW3D) - Play realtime animation in Blender" " (not rendered).\n" @@ -231,6 +208,7 @@ PyTypeObject Scene_Type = { 0, 0, 0, 0, 0, 0, BPy_Scene_methods, /* tp_methods */ 0, /* tp_members */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, }; //-----------------------Scene module Init())----------------------------- PyObject *Scene_Init( void ) @@ -264,10 +242,16 @@ static PyObject *Scene_getAttr( BPy_Scene * self, char *name ) if( strcmp( name, "name" ) == 0 ) attr = PyString_FromString( self->scene->id.name + 2 ); + /* accept both Layer (for compatibility with ob.Layer) and Layers */ + else if( strncmp( name, "Layer", 5 ) == 0 ) + attr = PyInt_FromLong( self->scene->lay ); + /* Layers returns a bitmask, layers returns a list of integers */ + else if( strcmp( name, "layers") == 0) { + return Scene_getLayers(self); + } else if( strcmp( name, "__members__" ) == 0 ) - attr = Py_BuildValue( "[s]", "name" ); - + attr = Py_BuildValue( "[ss]", "name", "Layers", "layers" ); if( !attr ) return ( EXPP_ReturnPyObjError( PyExc_MemoryError, @@ -302,8 +286,12 @@ static int Scene_setAttr( BPy_Scene * self, char *name, PyObject * value ) /* Now we just compare "name" with all possible BPy_Scene member variables */ if( strcmp( name, "name" ) == 0 ) error = Scene_setName( self, valtuple ); + else if (strncmp(name, "Layer", 5) == 0) + error = Scene_setLayersMask(self, valtuple); + else if (strcmp(name, "layers") == 0) + error = Scene_setLayers(self, valtuple); - else { /* Error: no member with the given name was found */ + else { /* Error: no member with the given name was found */ Py_DECREF( valtuple ); return ( EXPP_ReturnIntError( PyExc_AttributeError, name ) ); } @@ -559,6 +547,114 @@ static PyObject *Scene_setName( BPy_Scene * self, PyObject * args ) return Py_None; } +//-----------------------Scene.getLayers()--------------------------------- +static PyObject *Scene_getLayers( BPy_Scene * self ) +{ + PyObject *laylist = PyList_New( 0 ), *item; + int layers, bit = 0, val = 0; + + if( !laylist ) + return ( EXPP_ReturnPyObjError( PyExc_MemoryError, + "couldn't create pylist!" ) ); + + layers = self->scene->lay; + + while( bit < 20 ) { + val = 1 << bit; + if( layers & val ) { + item = Py_BuildValue( "i", bit + 1 ); + PyList_Append( laylist, item ); + Py_DECREF( item ); + } + bit++; + } + return laylist; +} + +//-----------------------Scene.setLayers()--------------------------------- +static PyObject *Scene_setLayers( BPy_Scene * self, PyObject * args ) +{ + PyObject *list = NULL, *item = NULL; + int layers = 0, val, i, len_list; + + if( !PyArg_ParseTuple( args, "O!", &PyList_Type, &list ) ) + return ( EXPP_ReturnPyObjError( PyExc_TypeError, + "expected a list of integers in the range [1, 20]" ) ); + + len_list = PyList_Size(list); + + if (len_list == 0) + return ( EXPP_ReturnPyObjError( PyExc_AttributeError, + "list can't be empty, at least one layer must be set" ) ); + + for( i = 0; i < len_list; i++ ) { + item = PyList_GetItem( list, i ); + if( !PyInt_Check( item ) ) + return EXPP_ReturnPyObjError + ( PyExc_AttributeError, + "list must contain only integer numbers" ); + + val = ( int ) PyInt_AsLong( item ); + if( val < 1 || val > 20 ) + return EXPP_ReturnPyObjError + ( PyExc_AttributeError, + "layer values must be in the range [1, 20]" ); + + layers |= 1 << ( val - 1 ); + } + self->scene->lay = layers; + + if (G.vd && (self->scene == G.scene)) { + int bit = 0; + G.vd->lay = layers; + + while( bit < 20 ) { + val = 1 << bit; + if( layers & val ) { + G.vd->layact = val; + break; + } + bit++; + } + } + + return EXPP_incr_ret(Py_None); +} + +/* only used by setAttr */ +static PyObject *Scene_setLayersMask(BPy_Scene *self, PyObject *args) +{ + int laymask = 0; + + if (!PyArg_ParseTuple(args , "i", &laymask)) { + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "expected an integer (bitmask) as argument" ); + } + + if (laymask <= 0 || laymask > 1048575) /* binary: 1111 1111 1111 1111 1111 */ + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "bitmask must have from 1 up to 20 bits set"); + + self->scene->lay = laymask; + /* if this is the current scene then apply the scene layers value + * to the view layers value: */ + if (G.vd && (self->scene == G.scene)) { + int val, bit = 0; + G.vd->lay = laymask; + + while( bit < 20 ) { + val = 1 << bit; + if( laymask & val ) { + G.vd->layact = val; + break; + } + bit++; + } + } + + return EXPP_incr_ret(Py_None); +} + //-----------------------Scene.copy()------------------------------------ static PyObject *Scene_copy( BPy_Scene * self, PyObject * args ) { @@ -825,14 +921,11 @@ static PyObject *Scene_addScriptLink( BPy_Scene * self, PyObject * args ) slink = &( scene )->scriptlink; - if( !EXPP_addScriptLink( slink, args, 1 ) ) - return EXPP_incr_ret( Py_None ); - else - return NULL; + return EXPP_addScriptLink( slink, args, 1 ); } /* scene.clearScriptLinks */ -static PyObject *Scene_clearScriptLinks( BPy_Scene * self ) +static PyObject *Scene_clearScriptLinks( BPy_Scene * self, PyObject * args ) { Scene *scene = self->scene; ScriptLink *slink = NULL; @@ -843,8 +936,7 @@ static PyObject *Scene_clearScriptLinks( BPy_Scene * self ) slink = &( scene )->scriptlink; - return EXPP_incr_ret( Py_BuildValue - ( "i", EXPP_clearScriptLinks( slink ) ) ); + return EXPP_clearScriptLinks( slink, args ); } /* scene.getScriptLinks */ @@ -926,62 +1018,3 @@ static PyObject *Scene_play( BPy_Scene * self, PyObject * args ) return ret; } - -/*****************************************************************************/ -// DEPRECATED -/*****************************************************************************/ -//-----------------------Scene.getRenderdir ()--------------------------- -static PyObject *Scene_getRenderdir( BPy_Scene * self ) -{ - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Deprecated:use RenderData.getRenderPath()" ); -} - -//-----------------------Scene.getBackbufdir ()-------------------------- -static PyObject *Scene_getBackbufdir( BPy_Scene * self ) -{ - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Deprecated:use RenderData.getBackbufPath()" ); -} - -//-----------------------Scene.startFrame ()----------------------------- -static PyObject *Scene_startFrame( BPy_Scene * self, PyObject * args ) -{ - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Deprecated:use RenderData.startFrame()" ); -} - -//-----------------------Scene.endFrame ()------------------------------- -static PyObject *Scene_endFrame( BPy_Scene * self, PyObject * args ) -{ - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Deprecated:use RenderData.endFrame()" ); -} - -//-----------------------Scene.getWinSize ()----------------------------- -static PyObject *Scene_getWinSize( BPy_Scene * self ) -{ - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Deprecated:use RenderData.imageSizeX() and RenderData.imageSizeY" ); -} - -//-----------------------Scene.setWinSize()------------------------------ -static PyObject *Scene_setWinSize( BPy_Scene * self, PyObject * args ) -{ - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Deprecated:use RenderData.imageSizeX() and RenderData.imageSizeY" ); -} - -//-----------------------Scene.frameSettings()--------------------------- -static PyObject *Scene_frameSettings( BPy_Scene * self, PyObject * args ) -{ - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Deprecated:use RenderData.startFrame(), RenderData.endFrame, RenderData.currentFrame" ); -} - -//-----------------------Scene.currentFrame()---------------------------- -static PyObject *Scene_currentFrame( BPy_Scene * self, PyObject * args ) -{ - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Deprecated:use RenderData.currentFrame" ); -} diff --git a/source/blender/python/api2_2x/Window.c b/source/blender/python/api2_2x/Window.c index b8998a943ac..64ce039d063 100644 --- a/source/blender/python/api2_2x/Window.c +++ b/source/blender/python/api2_2x/Window.c @@ -90,7 +90,7 @@ static PyObject *M_Window_GetPerspMatrix( PyObject * self ); static PyObject *M_Window_FileSelector( PyObject * self, PyObject * args ); static PyObject *M_Window_ImageSelector( PyObject * self, PyObject * args ); static PyObject *M_Window_EditMode( PyObject * self, PyObject * args ); -static PyObject *M_Window_ViewLayer( PyObject * self, PyObject * args ); +static PyObject *M_Window_ViewLayers( PyObject * self, PyObject * args ); static PyObject *M_Window_CameraView( PyObject * self, PyObject * args ); static PyObject *M_Window_QTest( PyObject * self ); static PyObject *M_Window_QRead( PyObject * self ); @@ -178,7 +178,7 @@ Returns the current status. This function is mostly useful to leave\n\ edit mode before applying changes to a mesh (otherwise the changes will\n\ be lost) and then returning to it upon leaving."; -static char M_Window_ViewLayer_doc[] = +static char M_Window_ViewLayers_doc[] = "(layers = []) - Get/set active layers in all 3d View windows.\n\ () - Make no changes, only return currently visible layers.\n\ (layers = []) - a list of integers, each in the range [1, 20].\n\ @@ -317,8 +317,11 @@ struct PyMethodDef M_Window_methods[] = { M_Window_GetPerspMatrix_doc}, {"EditMode", ( PyCFunction ) M_Window_EditMode, METH_VARARGS, M_Window_EditMode_doc}, - {"ViewLayer", ( PyCFunction ) M_Window_ViewLayer, METH_VARARGS, - M_Window_ViewLayer_doc}, + {"ViewLayers", ( PyCFunction ) M_Window_ViewLayers, METH_VARARGS, + M_Window_ViewLayers_doc}, + /* typo, deprecate someday: */ + {"ViewLayer", ( PyCFunction ) M_Window_ViewLayers, METH_VARARGS, + M_Window_ViewLayers_doc}, {"CameraView", ( PyCFunction ) M_Window_CameraView, METH_VARARGS, M_Window_CameraView_doc}, {"QTest", ( PyCFunction ) M_Window_QTest, METH_NOARGS, @@ -882,15 +885,15 @@ static PyObject *M_Window_EditMode( PyObject * self, PyObject * args ) return Py_BuildValue( "h", G.obedit ? 1 : 0 ); } -static PyObject *M_Window_ViewLayer( PyObject * self, PyObject * args ) +static PyObject *M_Window_ViewLayers( PyObject * self, PyObject * args ) { PyObject *item = NULL; PyObject *list = NULL, *resl = NULL; int val, i, bit = 0, layer = 0; - if( !G.vd ) { + if( !G.scene ) { return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "this function can only be used after a 3d View has been initialized" ); + "can't get pointer to global scene" ); } if( !PyArg_ParseTuple( args, "|O!", &PyList_Type, &list ) ) @@ -898,7 +901,13 @@ static PyObject *M_Window_ViewLayer( PyObject * self, PyObject * args ) "expected nothing or a list of ints as argument" ); if( list ) { - for( i = 0; i < PyList_Size( list ); i++ ) { + int len_list = PyList_Size(list); + + if (len_list == 0) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "list can't be empty, at list one layer must be set" ); + + for( i = 0; i < len_list; i++ ) { item = PyList_GetItem( list, i ); if( !PyInt_Check( item ) ) return EXPP_ReturnPyObjError @@ -913,15 +922,18 @@ static PyObject *M_Window_ViewLayer( PyObject * self, PyObject * args ) layer |= 1 << ( val - 1 ); } - G.vd->lay = layer; - - while( bit < 20 ) { - val = 1 << bit; - if( layer & val ) { - G.vd->layact = val; - break; + G.scene->lay = layer; + if (G.vd) { + G.vd->lay = layer; + + while( bit < 20 ) { + val = 1 << bit; + if( layer & val ) { + G.vd->layact = val; + break; + } + bit++; } - bit++; } } @@ -930,7 +942,7 @@ static PyObject *M_Window_ViewLayer( PyObject * self, PyObject * args ) return ( EXPP_ReturnPyObjError( PyExc_MemoryError, "couldn't create pylist!" ) ); - layer = G.vd->lay; + layer = G.scene->lay; bit = 0; while( bit < 20 ) { diff --git a/source/blender/python/api2_2x/World.c b/source/blender/python/api2_2x/World.c index e6c5b3b67a3..fa8b57bd809 100644 --- a/source/blender/python/api2_2x/World.c +++ b/source/blender/python/api2_2x/World.c @@ -97,7 +97,7 @@ static PyObject *World_getMist( BPy_World * self ); static PyObject *World_setMist( BPy_World * self, PyObject * args ); static PyObject *World_getScriptLinks( BPy_World * self, PyObject * args ); static PyObject *World_addScriptLink( BPy_World * self, PyObject * args ); -static PyObject *World_clearScriptLinks( BPy_World * self ); +static PyObject *World_clearScriptLinks( BPy_World * self, PyObject * args ); static PyObject *World_setCurrent( BPy_World * self ); @@ -217,8 +217,9 @@ static PyMethodDef BPy_World_methods[] = { "(text) - string: an existing Blender Text name;\n" "(evt) string: FrameChanged or Redraw."}, {"clearScriptLinks", ( PyCFunction ) World_clearScriptLinks, - METH_NOARGS, - "() - Delete all scriptlinks from this world :)."}, + METH_VARARGS, + "() - Delete all scriptlinks from this world.\n" + "([s1<,s2,s3...>]) - Delete specified scriptlinks from this world."}, {"setCurrent", ( PyCFunction ) World_setCurrent, METH_NOARGS, "() - Makes this world the active world for the current scene."}, {"makeActive", ( PyCFunction ) World_setCurrent, METH_NOARGS, @@ -856,22 +857,18 @@ static PyObject *World_addScriptLink( BPy_World * self, PyObject * args ) slink = &( world )->scriptlink; - if( !EXPP_addScriptLink( slink, args, 0 ) ) - return EXPP_incr_ret( Py_None ); - else - return NULL; + return EXPP_addScriptLink( slink, args, 0 ); } /* world.clearScriptLinks */ -static PyObject *World_clearScriptLinks( BPy_World * self ) +static PyObject *World_clearScriptLinks( BPy_World * self, PyObject * args ) { World *world = self->world; ScriptLink *slink = NULL; slink = &( world )->scriptlink; - return EXPP_incr_ret( Py_BuildValue - ( "i", EXPP_clearScriptLinks( slink ) ) ); + return EXPP_clearScriptLinks( slink, args ); } /* world.getScriptLinks */ diff --git a/source/blender/python/api2_2x/doc/API_intro.py b/source/blender/python/api2_2x/doc/API_intro.py index ce2b7d8fc93..9d54eac9d8a 100644 --- a/source/blender/python/api2_2x/doc/API_intro.py +++ b/source/blender/python/api2_2x/doc/API_intro.py @@ -30,8 +30,8 @@ The Blender Python API Reference - L{NMesh} (*) - L{Noise} - L{Object} (*) - - L{Registry} - - L{Scene} + - L{Registry} (*) + - L{Scene} (*) - L{Radio} - L{Render} - L{Sound} diff --git a/source/blender/python/api2_2x/doc/API_related.py b/source/blender/python/api2_2x/doc/API_related.py index 103a6c3d0a2..8326ee72279 100644 --- a/source/blender/python/api2_2x/doc/API_related.py +++ b/source/blender/python/api2_2x/doc/API_related.py @@ -238,29 +238,32 @@ Introduction: Configuring scripts: -------------------- - Configuration data is simple data used by your script (bools, ints, floats, - strings) to define default behaviors. - - For example, an exporter might have: - - EXPORT_LIGHTS = False: a bool variable (True / False) to determine if it - should also export lights setup information; - - VERSION = 2.0: an int to define an specific version of the export format; + The L{Blender.Registry<Registry>} module provides a simplified way to keep + scripts configuration options in memory and also saved in config files. + And with the "Scripts Config Editor" script in the System menu users can later + view and edit the options easily. + + Let's first clarify what we mean by config options: they are simple data + (bools, ints, floats, strings) used by programs to conform to user + preferences. The buttons in Blender's User Preferences window are a good + example. + + For example, a particular exporter might include: + - SEPARATE_MATS = False: a bool variable (True / False) to determine if it + should write materials to a separate file; + - VERSION = 2: an int to define an specific version of the export format; - TEX_DIR = "/path/to/textures": a default texture dir to prepend to all exported texture filenames instead of their actual paths. - To properly handle this, script writers had to keep this information in a - separate config file (at L{Blender.Get}('udatadir') or, if not available, - L{Blender.Get}('datadir')), provide a GUI to edit it and update the file - whenever needed. - - There are facilities in BPython now to take care of this in a simplified (and - much recommended) way. + The script needs to provide users a GUI to configure these options -- or else + directly editing the source code would be the only way to change them. And to + store changes made to the GUI so they can be reloaded any time the script is + executed, programmers have to write and load their own config files (ideally at + L{Blender.Get}('udatadir') or, if not available, L{Blender.Get}('datadir')). - The L{Registry} module functions L{GetKey<Registry.GetKey>} and - L{SetKey<Registry.SetKey>} take care of both keeping the data in Blender - and (new) storing it in config files at the proper dir. And the 'Scripts - Configuration Editor' script provides a GUI for users to view and edit - configuration data. + This section describes BPython facilities (based on the L{Registry} module and + the config editor) that can take care of this in a simplified (and much + recommended) way. Here's how it works:: @@ -269,16 +272,18 @@ Introduction: from Blender import Registry # First define all config variables with their default values: - EXPORT_LIGHTS = True - VERBOSE = True + SEPARATE_MATERIALS = True + VERSION = True + TEX_DIR = '' EXPORT_DIR = '' # Then define a function to update the Registry: def registry_update(): # populate a dict with current config values: d = { - 'EXPORT_LIGHTS': EXPORT_LIGHTS, - 'VERBOSE': VERBOSE, + 'SEPARATE_MATERIALS': SEPARATE_MATERIALS, + 'VERSION': VERSION, + 'TEX_DIR': TEX_DIR, 'EXPORT_DIR': EXPORT_DIR } # store the key (optional 3rd arg tells if @@ -292,9 +297,17 @@ Introduction: # If this key already exists, update config variables with its values: if regdict: - EXPORT_LIGHTS = regdict['EXPORT_LIGHTS'] - VERBOSE = regdict['VERBOSE'] - EXPORT_DIR = regdict['EXPORT_DIR'] + try: + SEPARATE_MATERIALS = regdict['SEPARATE_MATERIALS'] + VERSION = regdict['VERSION'] + TEX_DIR = regdict['TEX_DIR'] + EXPORT_DIR = regdict['EXPORT_DIR'] + + # if data was corrupted (or a new version of the script changed + # (expanded, removed, renamed) the config vars and users may have + # the old config file around): + except: update_registry() # rewrite it + else: # if the key doesn't exist yet, use our function to create it: update_registry() @@ -303,27 +316,25 @@ Introduction: Hint: nicer code than the simplistic example above can be written by keeping config var names in a list of strings and using the exec function. - B{Note}: if you have a gui and the user uses it to change config vars, - call the registry_update() function to save the changes. + B{Note}: if your script's GUI lets users change config vars, call the + registry_update() function in the button events callback to save the changes. On the other hand, you don't need to handle configuration in your own gui, it can be left for the 'Scripts Config Editor', which should have access to your script's config key as soon as the - above code is executed once. + above code is executed once (as soon as SetKey is executed). + + B{Note} (limits for config vars): strings longer than 300 characters are + clamped and the number of items in dictionaries, sequences and the config key + itself is limited to 60. - As written above, config vars can be bools, ints, floats or strings. This is - what the Config Editor supports, with sensible but generous limits for the - number of vars and the size of each string. Restrictions were suggested or - imposed to these facilities related to the Registry module because it's meant - for configuration info, not for large volumes of data. For that you can - trivially store it in a file or Blender Text yourself -- and tell the user - about it, specially if your script keeps megabytes of data in the Registry - memory. B{Scripts Configuration Editor}: - This script should be available from the Help menu and provides a GUI to - view and edit saved configuration data, both from the Registry dictionary in - memory and the scripts config data dir. + This script should be available from the System menu in the Scripts window. + It provides a GUI to view and edit saved configuration data, both from the + Registry dictionary in memory and the scripts config data dir. This is + useful for all scripts with config vars, but specially for those without GUI's, + like most importers and exporters, since this editor will provide one for them. The example above already gives a good idea of how the information can be prepared to be accessible from this editor, but there is more worth knowing: @@ -339,8 +350,8 @@ Introduction: 3. The following information refers to extra config variables that may be added specifically to aid the configuration editor script. To clarify, in the example code above these variables (the string 'script' and the dictionaries - 'tooltips' and 'limits') would appear along with EXPORT_LIGHTS, VERBOSE and - EXPORT_DIR, wherever they are written. + 'tooltips' and 'limits') would appear along with SEPARATE_MATERIALS, VERSION, + TEX_DIR and EXPORT_DIR, wherever they are written. Minor note: these names are case insensitive: tooltips, TOOLTIPS, etc. are all recognized. @@ -364,7 +375,7 @@ Introduction: tooltips = { 'EXPORT_DIR': 'default folder where exported files should be saved', 'VERBOSE': 'print info and warning messages to the console', - 'EXPORT_LIGHTS': 'export scene lighting setup' + 'SEPARATE_MATERIALS': 'write materials to their own file' } 3.3 Int and float button sliders need min and max limits. This can be passed @@ -373,5 +384,18 @@ Introduction: limits = {'ivar1': [-10, 10], 'ivar2': [0, 100], 'fvar1': [-12.3, 15.4]} + 4. The Config Editor itself maintains a Registry key called "General", with + general options relevant to many scripts, like "verbose" to tell if the user + wants messages printed to the console and "confirm overwrite", to know if + a script should ask for confirmation before overwriting files (all exporters + are recommended to access the General key and check this var -- L{sys.exists + <Sys.exists>} tells if files or folders already exist). + + Hint: for actual examples, try the ac3d importer and exporter (it's enough to + call them from the menus then cancel with ESC), as those have been updated to + use this config system. After calling them their config data will be available + in the Config Editor. We also recommend adding a section about config vars + in your script's help info, as done in the ac3d ones. + L{Back to Main Page<API_intro>} """ diff --git a/source/blender/python/api2_2x/doc/Blender.py b/source/blender/python/api2_2x/doc/Blender.py index 1aa7f81c703..b68d9a40d60 100644 --- a/source/blender/python/api2_2x/doc/Blender.py +++ b/source/blender/python/api2_2x/doc/Blender.py @@ -60,7 +60,8 @@ def Get (request): - 'udatadir': the path to the user defined data dir. This may not be available (is None if not found), but users that define uscriptsdir have a place for their own scripts and script data that won't be - erased when a new version of Blender is installed. + erased when a new version of Blender is installed. For this reason + we recommend scripts check this dir first and use it, if available. - 'scriptsdir': the path to the main dir where scripts are stored. - 'uscriptsdir': the path to the user defined dir for scripts. (*) - 'yfexportdir': the path to the user defined dir for yafray export. (*) diff --git a/source/blender/python/api2_2x/doc/Camera.py b/source/blender/python/api2_2x/doc/Camera.py index 7fcc94834c5..9dc382a2ba8 100644 --- a/source/blender/python/api2_2x/doc/Camera.py +++ b/source/blender/python/api2_2x/doc/Camera.py @@ -3,7 +3,7 @@ """ The Blender.Camera submodule. -B{New}: L{Camera.getScale}, L{Camera.setScale} for ortho cameras. +B{New}: L{Camera.clearScriptLinks} accepts a parameter now. Camera Data =========== @@ -211,11 +211,12 @@ class Camera: 'event' type) or None if there are no script links at all. """ - def clearScriptLinks (): + def clearScriptLinks (links = None): """ - Delete all this Camera's script links. - @rtype: bool - @return: 0 if some internal problem occurred or 1 if successful. + Delete script links from this Camera. If no list is specified, all + script links are deleted. + @type links: list of strings + @param links: None (default) or a list of Blender L{Text} names. """ def addScriptLink (text, event): diff --git a/source/blender/python/api2_2x/doc/Lamp.py b/source/blender/python/api2_2x/doc/Lamp.py index 0b781ef6f3f..824e43eaad2 100644 --- a/source/blender/python/api2_2x/doc/Lamp.py +++ b/source/blender/python/api2_2x/doc/Lamp.py @@ -3,7 +3,7 @@ """ The Blender.Lamp submodule. -B{New}: scriptLink methods: L{Lamp.getScriptLinks}, ... +B{New}: L{Lamp.clearScriptLinks} accepts a parameter now. Lamp Data ========= @@ -335,11 +335,12 @@ class Lamp: 'event' type) or None if there are no script links at all. """ - def clearScriptLinks (): + def clearScriptLinks (links = None): """ - Delete all this Lamp's script links. - @rtype: bool - @return: 0 if some internal problem occurred or 1 if successful. + Delete script links from this Lamp. If no list is specified, all + script links are deleted. + @type links: list of strings + @param links: None (default) or a list of Blender L{Text} names. """ def addScriptLink (text, event): diff --git a/source/blender/python/api2_2x/doc/Material.py b/source/blender/python/api2_2x/doc/Material.py index 8997fc1b402..79d28b1162b 100644 --- a/source/blender/python/api2_2x/doc/Material.py +++ b/source/blender/python/api2_2x/doc/Material.py @@ -3,7 +3,7 @@ """ The Blender.Material submodule. -B{New}: scriptLink methods: L{Material.getScriptLinks}, ... +B{New}: L{Material.clearScriptLinks} accepts a parameter now. Material ======== @@ -643,11 +643,12 @@ class Material: 'event' type) or None if there are no script links at all. """ - def clearScriptLinks (): + def clearScriptLinks (links = None): """ - Delete all this Material's script links. - @rtype: bool - @return: 0 if some internal problem occurred or 1 if successful. + Delete script links from this Material. If no list is specified, all + script links are deleted. + @type links: list of strings + @param links: None (default) or a list of Blender L{Text} names. """ def addScriptLink (text, event): diff --git a/source/blender/python/api2_2x/doc/NMesh.py b/source/blender/python/api2_2x/doc/NMesh.py index fb7b1a8e735..d2662942a09 100644 --- a/source/blender/python/api2_2x/doc/NMesh.py +++ b/source/blender/python/api2_2x/doc/NMesh.py @@ -601,7 +601,7 @@ class NMesh: from Blender import NMesh, Object ob = Object.GetSelected()[0] # Get the first selected object - me = NMesh.GetRawFromObject(ob) # Get the objects deformed mesh data + me = NMesh.GetRawFromObject(ob.name) # Get the objects deformed mesh data me.transform(ob.matrix) for v in me.verts: diff --git a/source/blender/python/api2_2x/doc/Object.py b/source/blender/python/api2_2x/doc/Object.py index 1dc8ee4413e..e75c2cc4234 100644 --- a/source/blender/python/api2_2x/doc/Object.py +++ b/source/blender/python/api2_2x/doc/Object.py @@ -3,8 +3,13 @@ """ The Blender.Object submodule -B{New}: L{Object.getData} now accepts an optional bool keyword argument to -define if the user wants the data object or just its name. +B{New}: + - L{Object.getData} now accepts an optional bool keyword argument to + define if the user wants the data object or just its name. + - L{Object.clearScriptLinks} accepts a parameter now. + - Object attributes: renamed Layer to L{Layers<Object.Object.Layers>} and + added the easier L{layers<Object.Object.layers>}. The old form "Layer" + will continue to work. Object ====== @@ -135,13 +140,31 @@ class Object: @cvar EffX: The X effector coordinate of the object. Only applies to IKA. @cvar EffY: The Y effector coordinate of the object. Only applies to IKA. @cvar EffZ: The Z effector coordinate of the object. Only applies to IKA. - @cvar Layer: The object layer. This value is a bitmask with one position - set for each of the 20 possible layers starting from the low order bit. - The easiest way to deal with these values in in hexadecimal notation. + @type Layers: integer (bitmask) + @cvar Layers: The object layers (also check the newer attribute + L{layers<Object.Object.layers>}). This value is a bitmask with at + least one position set for the 20 possible layers starting from the low + order bit. The easiest way to deal with these values in in hexadecimal + notation. Example:: ob.Layer = 0x04 # sets layer 3 ( bit pattern 0100 ) After setting the Layer value, call Blender.Redraw( -1 ) to update the interface. + @type layers: list of integers + @cvar layers: The layers this object is visible in (also check the older + attribute L{Layers<Object.Object.Layers>}). This returns a list of + integers in the range [1, 20], each number representing the respective + layer. Setting is done by passing a list of ints or an empty list for + no layers. + Example:: + ob.layers = [] # object won't be visible + ob.layers = [1, 4] # object visible only in layers 1 and 4 + ls = o.layers + ls.append([10]) + o.layers = ls + print ob.layers # will print: [1, 4, 10] + B{Note}: changes will only be visible after the screen (at least + the 3d View and Buttons windows) is redrawn. @cvar parent: The parent object of the object. (Read-only) @cvar track: The object tracking this object. (Read-only) @cvar data: The data of the object. (Read-only) @@ -578,11 +601,12 @@ class Object: 'event' type) or None if there are no script links at all. """ - def clearScriptLinks (): + def clearScriptLinks (links = None): """ - Delete all this Object's script links. - @rtype: bool - @return: 0 if some internal problem occurred or 1 if successful. + Delete script links from this Object. If no list is specified, all + script links are deleted. + @type links: list of strings + @param links: None (default) or a list of Blender L{Text} names. """ def addScriptLink (text, event): diff --git a/source/blender/python/api2_2x/doc/Registry.py b/source/blender/python/api2_2x/doc/Registry.py index 5913505f4e4..e80a0e1fffa 100644 --- a/source/blender/python/api2_2x/doc/Registry.py +++ b/source/blender/python/api2_2x/doc/Registry.py @@ -3,55 +3,35 @@ """ The Blender.Registry submodule. -B{New}: L{GetKey} and L{SetKey} can respectively load and save data to disk now. +B{New}: L{GetKey} and L{SetKey} have been updated to save and load scripts +*configuration data* to files. Registry ======== This module provides a way to create, retrieve and edit B{persistent data} in -Blender. When a script runs in Blender, it has its own private global -dictionary, which is deleted when the script finishes. This is done to avoid -problems with name clashes and garbage collecting. But the result is that -data created by a script isn't kept after it leaves, for itself or others to -access later: the data isn't persistent. The Registry module was created to -give script authors a way around this limitation. - -In Python terms, the Registry holds a dictionary of dictionaries. -You should use it to save Python objects only, not BPython (Blender Python) -objects -- but you can save BPython object names, since those are strings. -Also, if you need to save a considerable amount of data, we recommend saving -it to a file instead. There's no need to keep huge blocks of memory around when -they can simply be read from a file. - -Examples of what this module can be used for: - -a) Saving data from a script that another script will need to access later. - -b) Saving configuration data for a script. Users can view and edit this data -using the "Scripts Configuration Editor" script, then. - -c) Saving configuration data from your script's gui (button values) so that the -next time the user runs your script, the changes will still be there. +Blender. + +When a script is executed it has its own private global dictionary, +which is deleted when the script exits. This is done to avoid problems with +name clashes and garbage collecting. But because of this, the data created by +a script isn't kept after it leaves: the data is not persistent. The Registry +module was created to give programmers a way around this limitation. + +Possible uses: + - saving arbitrary data from a script that itself or another one will need + to access later. + - saving configuration data for a script: users can view and edit this data + using the "Scripts Configuration Editor" script. + - saving the current state of a script's GUI (its button values) to restore it + when the script is executed again. Example:: import Blender from Blender import Registry - # first declare your global variables: - myvar1 = 0 - myvar2 = 3.2 - mystr = "hello" - - # then check if they are already at the Registry (saved on a - # previous execution of this script) or on disk: - rdict = Registry.GetKey('MyScript', True) - if rdict: # if found, get the values saved there - myvar1 = rdict['myvar1'] - myvar2 = rdict['myvar2'] - mystr = rdict['mystr'] - - # let's create a function to update the Registry when we need to: + # this function updates the Registry when we need to: def update_Registry(): d = {} d['myvar1'] = myvar1 @@ -60,14 +40,49 @@ Example:: # cache = True: data is also saved to a file Blender.Registry.SetKey('MyScript', d, True) + # first declare global variables that should go to the Registry: + myvar1 = 0 + myvar2 = 3.2 + mystr = "hello" + + # then check if they are already there (saved on a + # previous execution of this script): + rdict = Registry.GetKey('MyScript', True) # True to check on disk also + if rdict: # if found, get the values saved there + try: + myvar1 = rdict['myvar1'] + myvar2 = rdict['myvar2'] + mystr = rdict['mystr'] + except: update_Registry() # if data isn't valid rewrite it + # ... # here goes the main part of the script ... # ... - # at the end, before exiting, we use our helper function: + # if at some point the data is changed, we update the Registry: update_Registry() - # note1: better not update the Registry when the user cancels the script - # note2: most scripts shouldn't need to register more than one key. + +@note: In Python terms, the Registry holds a dictionary of dictionaries. + Technically any Python or BPython object can be stored: there are no + restrictions, but ... + +@note: We have a few recommendations: + + Data saved to the Registry is kept in memory, so if you decide to store large + amounts your script users should be clearly informed about it -- + always keep in mind that you have no idea about their resources and the + applications they are running at a given time (unless you are the only + user), so let them decide. + + There are restrictions to the data that gets automatically saved to disk by + L{SetKey}(keyname, dict, True): this feature is only meant for simple data + (bools, ints, floats, strings and dictionaries or sequences of these types). + Strings are clamped if longer than 300 characters and at most 60 elements are + allowed. Since this is only meant for scripts configuration variables, + these are sensible restrictions, generous enough for the task. + + For more demanding needs, it's of course trivial to save data to another + file or to a L{Blender Text<Text>}. """ def Keys (): @@ -97,7 +112,9 @@ def SetKey (key, dict, cache = False): @type cache: bool @param cache: if True the given key data will also be saved as a file in the config subdir of the scripts user or default data dir (see - L{Blender.Get}. + L{Blender.Get}). + @warn: as stated in the notes above, there are restrictions to what can + be automatically stored in config files. """ def RemoveKey (key): diff --git a/source/blender/python/api2_2x/doc/Scene.py b/source/blender/python/api2_2x/doc/Scene.py index 692aea93f7d..815084b72e9 100644 --- a/source/blender/python/api2_2x/doc/Scene.py +++ b/source/blender/python/api2_2x/doc/Scene.py @@ -3,7 +3,10 @@ """ The Blender.Scene submodule. -B{New}: OnSave script link event: L{Scene.getScriptLinks}. +B{New}: + - L{Scene.clearScriptLinks} accepts a parameter now. + - L{Scene.getLayers}, L{Scene.setLayers} and the L{layers<Scene.layers>} and + L{Layers<Scene.Layers>} Scene attributes. Scene ===== @@ -75,7 +78,28 @@ class Scene: The Scene object ================ This object gives access to Scene data in Blender. + @type name: string @cvar name: The Scene name. + @type Layers: integer (bitmask) + @cvar Layers: The Scene layers (check also the easier to use + L{layers<Scene.Scene.layers>}). This value is a bitmask with at least + one position set for the 20 possible layers starting from the low order + bit. The easiest way to deal with these values in in hexadecimal + notation. + Example:: + scene.Layers = 0x04 # sets layer 3 ( bit pattern 0100 ) + scene.Layers |= 0x01 + print scene.Layers # will print: 5 ( meaning bit pattern 0101) + After setting the Layers value, the interface (at least the 3d View and + the Buttons window) needs to be redrawn to show the changes. + @type layers: list of integers + @cvar layers: The Scene layers (check also L{Layers<Scene.Scene.Layers>}). + This attribute accepts and returns a list of integer values in the + range [1, 20]. + Example:: + scene.layers = [3] # set layer 3 + scene.layers = scene.layers.append(1) + print scene.layers # will print: [1, 3] """ def getName(): @@ -91,6 +115,25 @@ class Scene: @param name: The new name. """ + def getLayers(): + """ + Get the layers set for this Scene. + @rtype: list of integers + @return: a list where each number means the layer with that number is + set. + """ + + def setLayers(layers): + """ + Set the visible layers for this scene. + @type layers: list of integers + @param layers: a list of integers in the range [1, 20], where each available + index makes the layer with that number visible. + @note: if this Scene is the current one, the 3D View layers are also + updated, but the screen needs to be redrawn (at least 3D Views and + Buttons windows) for the changes to be seen. + """ + def copy(duplicate_objects = 1): """ Make a copy of this Scene. @@ -139,6 +182,11 @@ class Scene: Get all objects linked to this Scene. @rtype: list of Blender Objects @return: A list with all Blender Objects linked to this Scene. + @note: L{Object.Get} will return all objects currently in Blender, which + means all objects from all available scenes. In most cases (exporter + scripts, for example), it's probably better to use this + scene.GetChildren instead, since it will only access objects from this + particular scene. """ def getCurrentCamera(): @@ -179,11 +227,12 @@ class Scene: 'event' type) or None if there are no script links at all. """ - def clearScriptLinks (): + def clearScriptLinks (links = None): """ - Delete all this Scene's script links. - @rtype: bool - @return: 0 if some internal problem occurred or 1 if successful. + Delete script links from this Scene. If no list is specified, all + script links are deleted. + @type links: list of strings + @param links: None (default) or a list of Blender L{Text} names. """ def addScriptLink (text, event): diff --git a/source/blender/python/api2_2x/doc/Window.py b/source/blender/python/api2_2x/doc/Window.py index 0b41a3038c7..caaf22710d8 100644 --- a/source/blender/python/api2_2x/doc/Window.py +++ b/source/blender/python/api2_2x/doc/Window.py @@ -3,6 +3,9 @@ """ The Blender.Window submodule. +B{New}: renamed ViewLayer to L{ViewLayers} (actually added an alias, so both +forms will work). + Window ====== @@ -263,7 +266,7 @@ def EditMode(enable = -1, undo_msg = 'From script'): because the normal mesh will be rebuilt based on its unchanged edit mesh. """ -def ViewLayer (layers = []): +def ViewLayers (layers = []): """ Get and optionally set the currently visible layers in all 3d Views. @type layers: list of ints diff --git a/source/blender/python/api2_2x/doc/World.py b/source/blender/python/api2_2x/doc/World.py index a6d1fba65b6..2aa333b6610 100644 --- a/source/blender/python/api2_2x/doc/World.py +++ b/source/blender/python/api2_2x/doc/World.py @@ -3,10 +3,10 @@ """ The Blender.World submodule -B{New}: L{GetCurrent}, L{World.setCurrent}. +B{New}: L{World.clearScriptLinks} accepts a parameter now. -INTRODUCTION -============ +World +===== The module world allows you to access all the data of a Blender World. @@ -299,11 +299,12 @@ class World: 'event' type) or None if there are no script links at all. """ - def clearScriptLinks (): + def clearScriptLinks (links = None): """ - Delete all this World's script links! - @rtype: bool - @return: 0 if some internal problem occurred or 1 if successful. + Delete script links from this World :). If no list is specified, all + script links are deleted. + @type links: list of strings + @param links: None (default) or a list of Blender L{Text} names. """ def addScriptLink (text, event): diff --git a/source/blender/python/api2_2x/gen_utils.c b/source/blender/python/api2_2x/gen_utils.c index 124a39503a0..ecdcc11e9f7 100644 --- a/source/blender/python/api2_2x/gen_utils.c +++ b/source/blender/python/api2_2x/gen_utils.c @@ -25,7 +25,7 @@ * * This is a new part of Blender. * - * Contributor(s): Michel Selten, Willian P. Germano, Alex Mole + * Contributor(s): Michel Selten, Willian P. Germano, Alex Mole, Ken Hughes * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ @@ -332,25 +332,106 @@ PyObject *EXPP_getScriptLinks( ScriptLink * slink, PyObject * args, return list; } -int EXPP_clearScriptLinks( ScriptLink * slink ) +PyObject *EXPP_clearScriptLinks( ScriptLink * slink, PyObject * args ) { - /* actually !scriptlink shouldn't happen ... */ - if( !slink || !slink->totscript ) - return -1; + int i, j, totLinks, deleted = 0; + PyObject *seq = NULL; + ID **stmp = NULL; + short *ftmp = NULL; + + /* check for an optional list of strings */ + if( !PyArg_ParseTuple( args, "|O", &seq ) ) + return ( EXPP_ReturnPyObjError + ( PyExc_TypeError, + "expected no arguments or a list of strings" ) ); + + + /* if there was a parameter, handle it */ + if ( seq != NULL ) { + /* check that parameter IS list of strings */ + if ( !PyList_Check ( seq ) ) + return ( EXPP_ReturnPyObjError + ( PyExc_TypeError, + "expected a list of strings" ) ); + + totLinks = PyList_Size ( seq ); + for ( i = 0 ; i < totLinks ; ++i ) { + if ( !PyString_Check ( PySequence_GetItem( seq, i ) ) ) + return ( EXPP_ReturnPyObjError + ( PyExc_TypeError, + "expected list to contain strings" ) ); + } - if( slink->scripts ) - MEM_freeN( slink->scripts ); - if( slink->flag ) - MEM_freeN( slink->flag ); + /* + parameters OK: now look for each script, and delete + its link as we find it (this handles multiple links) + */ + for ( i = 0 ; i < totLinks ; ++i ) + { + char *str; + str = PyString_AsString ( PySequence_GetItem( seq, i ) ); + for ( j = 0 ; j < slink->totscript ; ++j ) { + if ( slink->scripts[j] && !strcmp ( slink->scripts[j]->name+2, str ) ) { + slink->scripts[j] = NULL; + ++deleted; + } + } + } + } + /* if no parameter, then delete all scripts */ + else { + deleted = slink->totscript; + } - slink->scripts = NULL; - slink->flag = NULL; - slink->totscript = slink->actscript = 0; + /* + if not all scripts deleted, create new lists and copy remaining + links to them + */ + + if ( slink->totscript > deleted ) { + slink->totscript -= deleted; + + stmp = slink->scripts; + slink->scripts = + MEM_mallocN( sizeof( ID * ) * ( slink->totscript ), + "bpySlinkL" ); + + ftmp = slink->flag; + slink->flag = + MEM_mallocN( sizeof( short * ) * ( slink->totscript ), + "bpySlinkF" ); + + for ( i = 0, j = 0 ; i < slink->totscript ; ++j ) { + if ( stmp[j] != NULL ) { + memcpy( slink->scripts+i, stmp+j, sizeof( ID * ) ); + memcpy( slink->flag+i, ftmp+j, sizeof( short ) ); + ++i; + } + } + MEM_freeN( stmp ); + MEM_freeN( ftmp ); - return 0; /* normal return */ + /*EXPP_allqueue (REDRAWBUTSSCRIPT, 0 );*/ + slink->actscript = 1; + } else { + + /* all scripts deleted, so delete entire list and free memory */ + + if( slink->scripts ) + MEM_freeN( slink->scripts ); + if( slink->flag ) + MEM_freeN( slink->flag ); + + slink->scripts = NULL; + slink->flag = NULL; + slink->totscript = slink->actscript = 0; + } + + return EXPP_incr_ret( Py_None ); } -int EXPP_addScriptLink( ScriptLink * slink, PyObject * args, int is_scene ) + +PyObject *EXPP_addScriptLink(ScriptLink *slink, PyObject *args, int is_scene) { int event = 0, found_txt = 0; void *stmp = NULL, *ftmp = NULL; @@ -360,13 +441,13 @@ int EXPP_addScriptLink( ScriptLink * slink, PyObject * args, int is_scene ) /* !scriptlink shouldn't happen ... */ if( !slink ) { - return EXPP_ReturnIntError( PyExc_RuntimeError, - "internal error: no scriptlink!" ); + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "internal error: no scriptlink!" ); } if( !PyArg_ParseTuple( args, "ss", &textname, &eventname ) ) - return EXPP_ReturnIntError( PyExc_TypeError, - "expected two strings as arguments" ); + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected two strings as arguments" ); while( bltxt ) { if( !strcmp( bltxt->id.name + 2, textname ) ) { @@ -377,8 +458,8 @@ int EXPP_addScriptLink( ScriptLink * slink, PyObject * args, int is_scene ) } if( !found_txt ) - return EXPP_ReturnIntError( PyExc_AttributeError, - "no such Blender Text." ); + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "no such Blender Text" ); if( !strcmp( eventname, "FrameChanged" ) ) event = SCRIPT_FRAMECHANGED; @@ -390,7 +471,7 @@ int EXPP_addScriptLink( ScriptLink * slink, PyObject * args, int is_scene ) event = SCRIPT_ONSAVE; else return EXPP_ReturnIntError( PyExc_AttributeError, - "invalid event name." ); + "invalid event name" ); stmp = slink->scripts; slink->scripts = @@ -420,5 +501,5 @@ int EXPP_addScriptLink( ScriptLink * slink, PyObject * args, int is_scene ) if( slink->actscript < 1 ) slink->actscript = 1; - return 0; /* normal exit */ + return EXPP_incr_ret (Py_None); /* normal exit */ } diff --git a/source/blender/python/api2_2x/gen_utils.h b/source/blender/python/api2_2x/gen_utils.h index e2c1dfe82a0..235e0c5e8ce 100644 --- a/source/blender/python/api2_2x/gen_utils.h +++ b/source/blender/python/api2_2x/gen_utils.h @@ -89,10 +89,9 @@ int EXPP_map_getStrVal( const EXPP_map_pair * map, int ival, const char **sval ); /* scriplinks-related: */ -PyObject *EXPP_getScriptLinks( ScriptLink * slink, PyObject * args, - int is_scene ); -int EXPP_clearScriptLinks( ScriptLink * slink ); -int EXPP_addScriptLink( ScriptLink * slink, PyObject * args, int is_scene ); +PyObject *EXPP_getScriptLinks(ScriptLink *slink, PyObject *args, int is_scene); +PyObject *EXPP_addScriptLink(ScriptLink *slink, PyObject *args, int is_scene); +PyObject *EXPP_clearScriptLinks(ScriptLink *slink, PyObject *args); /* this queues redraws if we're not in background mode: */ void EXPP_allqueue(unsigned short event, short val); diff --git a/source/blender/python/api2_2x/windowTheme.c b/source/blender/python/api2_2x/windowTheme.c index 4464fb83b96..69ba451f2f5 100644 --- a/source/blender/python/api2_2x/windowTheme.c +++ b/source/blender/python/api2_2x/windowTheme.c @@ -119,6 +119,7 @@ PyTypeObject ThemeSpace_Type = { 0, 0, 0, 0, 0, 0, 0, //BPy_ThemeSpace_methods, /* tp_methods */ 0, /* tp_members */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, }; static void ThemeSpace_dealloc( BPy_ThemeSpace * self ) @@ -295,6 +296,7 @@ PyTypeObject ThemeUI_Type = { 0, 0, 0, 0, 0, 0, 0, //BPy_ThemeUI_methods, /* tp_methods */ 0, /* tp_members */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, }; static void ThemeUI_dealloc( BPy_ThemeUI * self ) @@ -468,8 +470,9 @@ PyTypeObject Theme_Type = { 0, 0, 0, 0, 0, 0, 0, /* tp_doc */ 0, 0, 0, 0, 0, 0, - 0, //BPy_Theme_methods, /* tp_methods */ + 0, /*BPy_Theme_methods,*/ /* tp_methods */ 0, /* tp_members */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, }; static PyObject *M_Theme_New( PyObject * self, PyObject * args ) |