diff options
author | Stephen Swaney <sswaney@centurytel.net> | 2005-06-13 23:15:02 +0400 |
---|---|---|
committer | Stephen Swaney <sswaney@centurytel.net> | 2005-06-13 23:15:02 +0400 |
commit | 769fa6252d90666768fc13a39eedecee12d8c0df (patch) | |
tree | 0fd2df014f63cf1e0112b7134f05d555f7a943d4 /source/blender/python | |
parent | de567cd0cc5532d3a6aa521328230239fa082810 (diff) |
Patch from Martin Poirier.
Misc bpy Curve fixes and updates, includes bugs #1687 and #2637
Diffstat (limited to 'source/blender/python')
-rw-r--r-- | source/blender/python/api2_2x/BezTriple.c | 318 | ||||
-rw-r--r-- | source/blender/python/api2_2x/BezTriple.h | 19 | ||||
-rw-r--r-- | source/blender/python/api2_2x/Blender.c | 2 | ||||
-rw-r--r-- | source/blender/python/api2_2x/CurNurb.c | 275 | ||||
-rw-r--r-- | source/blender/python/api2_2x/Curve.c | 28 | ||||
-rw-r--r-- | source/blender/python/api2_2x/Curve.h | 1 | ||||
-rw-r--r-- | source/blender/python/api2_2x/doc/Curve.py | 42 | ||||
-rw-r--r-- | source/blender/python/api2_2x/modules.h | 1 |
8 files changed, 583 insertions, 103 deletions
diff --git a/source/blender/python/api2_2x/BezTriple.c b/source/blender/python/api2_2x/BezTriple.c index a6a020b0537..849b2637522 100644 --- a/source/blender/python/api2_2x/BezTriple.c +++ b/source/blender/python/api2_2x/BezTriple.c @@ -24,7 +24,8 @@ * * This is a new part of Blender. * - * Contributor(s): Jacques Guignot + * Contributor(s): Jacques Guignot RIP 2005, + * Stephen Swaney * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ @@ -39,48 +40,57 @@ #include <BKE_library.h> #include <BLI_blenlib.h> #include <DNA_ipo_types.h> +#include <MEM_guardedalloc.h> #include "constant.h" #include "gen_utils.h" -/*****************************************************************************/ -/* Python API function prototypes for the BezTriple module. */ -/*****************************************************************************/ +/*************************************************************************** + Python API function prototypes for the BezTriple module. +***************************************************************************/ static PyObject *M_BezTriple_New( PyObject * self, PyObject * args ); static PyObject *M_BezTriple_Get( PyObject * self, PyObject * args ); -/*****************************************************************************/ -/* Python C_BezTriple instance methods declarations: */ -/*****************************************************************************/ -static PyObject *BezTriple_setPoints( C_BezTriple * self, PyObject * args ); -static PyObject *BezTriple_getPoints( C_BezTriple * self ); -static PyObject *BezTriple_getTriple( C_BezTriple * self ); +/************************************* + Doc strings for the BezTriple module +*************************************/ -/*****************************************************************************/ -/* Python BezTriple_Type callback function prototypes: */ -/*****************************************************************************/ -static void BezTripleDeAlloc( C_BezTriple * self ); -static int BezTripleSetAttr( C_BezTriple * self, char *name, PyObject * v ); -static PyObject *BezTripleGetAttr( C_BezTriple * self, char *name ); -static PyObject *BezTripleRepr( C_BezTriple * self ); +static char M_BezTriple_doc[] = "The Blender BezTriple module\n"; -/*****************************************************************************/ -/* Python method structure definition for Blender.BezTriple module: */ -/*****************************************************************************/ +/**************************************************************************** + Python BPy_BezTriple instance methods declarations: +****************************************************************************/ +static PyObject *BezTriple_setPoints( BPy_BezTriple * self, PyObject * args ); +static PyObject *BezTriple_getPoints( BPy_BezTriple * self ); +static PyObject *BezTriple_getTriple( BPy_BezTriple * self ); + +/**************************************************************************** + Python BezTriple_Type callback function prototypes: +*****************************************************************************/ +static void BezTripleDeAlloc( BPy_BezTriple * self ); +static int BezTripleSetAttr( BPy_BezTriple * self, char *name, PyObject * v ); +static PyObject *BezTripleGetAttr( BPy_BezTriple * self, char *name ); +static PyObject *BezTripleRepr( BPy_BezTriple * self ); +static PyObject *BezTriple_Str( BPy_BezTriple * self ); + +/**************************************************************************** + Python method structure definition for Blender.BezTriple module: +****************************************************************************/ struct PyMethodDef M_BezTriple_methods[] = { {"New", ( PyCFunction ) M_BezTriple_New, METH_VARARGS | METH_KEYWORDS, 0}, +/* {"New", ( PyCFunction ) M_BezTriple_New, METH_O, 0}, */ {"Get", M_BezTriple_Get, METH_VARARGS, 0}, {"get", M_BezTriple_Get, METH_VARARGS, 0}, {NULL, NULL, 0, NULL} }; /*****************************************************************************/ -/* Python C_BezTriple methods table: */ +/* Python BPy_BezTriple methods table: */ /*****************************************************************************/ -static PyMethodDef C_BezTriple_methods[] = { +static PyMethodDef BPy_BezTriple_methods[] = { /* name, method, flags, doc */ {"setPoints", ( PyCFunction ) BezTriple_setPoints, METH_VARARGS, "(str) - Change BezTriple point coordinates"}, @@ -96,10 +106,10 @@ static PyMethodDef C_BezTriple_methods[] = { /* Python BezTriple_Type structure definition: */ /*****************************************************************************/ PyTypeObject BezTriple_Type = { - PyObject_HEAD_INIT( NULL ) /* required python macro */ - 0, /* ob_size */ + PyObject_HEAD_INIT( NULL ) /* required python macro */ + 0, /* ob_size */ "BezTriple", /* tp_name */ - sizeof( C_BezTriple ), /* tp_basicsize */ + sizeof( BPy_BezTriple ), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ ( destructor ) BezTripleDeAlloc, /* tp_dealloc */ @@ -112,49 +122,71 @@ PyTypeObject BezTriple_Type = { 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_as_hash */ - 0, 0, 0, 0, 0, 0, + 0, /* tp_call */ + 0, /* ( reprfunc) BezTriple_Str, tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + 0, /* tp_flags */ 0, /* tp_doc */ 0, 0, 0, 0, 0, 0, - C_BezTriple_methods, /* tp_methods */ + BPy_BezTriple_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tm_getset */ 0 }; -/*****************************************************************************/ -/* Function: M_BezTriple_New */ -/* Python equivalent: Blender.BezTriple.New */ -/*****************************************************************************/ -static PyObject *M_BezTriple_New( PyObject * self, PyObject * args ) +/**************************************************************************** + Function: M_BezTriple_New + Python equivalent: Blender.BezTriple.New +****************************************************************************/ + +static PyObject *M_BezTriple_New( PyObject* self, PyObject * args ) { - return 0; + PyObject* in_args = NULL; + + if( !PyArg_ParseTuple( args, "|O", &in_args) ) { + return( EXPP_ReturnPyObjError + ( PyExc_AttributeError, + "expected sequence of 3 or 9 floats or nothing")); + } + + if( !in_args ) { + in_args = Py_BuildValue( "(fff)", 0.0, 0.0, 0.0 ); + } + + return newBezTriple( in_args ); } -/*****************************************************************************/ -/* Function: M_BezTriple_Get */ -/* Python equivalent: Blender.BezTriple.Get */ -/* Description: Receives a string and returns the ipo data obj */ -/* whose name matches the string. If no argument is */ -/* passed in, a list of all ipo data names in the */ -/* current scene is returned. */ -/*****************************************************************************/ +/**************************************************************************** + Function: M_BezTriple_Get + Python equivalent: Blender.BezTriple.Get + Description: Receives a string and returns the ipo data obj + whose name matches the string. If no argument is + passed in, a list of all ipo data names in the + current scene is returned. +****************************************************************************/ static PyObject *M_BezTriple_Get( PyObject * self, PyObject * args ) { return 0; } -/*****************************************************************************/ -/* Function: BezTripleDeAlloc */ -/* Description: This is a callback function for the C_BezTriple type. It is */ -/* the destructor function. */ -/*****************************************************************************/ -static void BezTripleDeAlloc( C_BezTriple * self ) +/**************************************************************************** + Function: BezTripleDeAlloc + Description: This is a callback function for the BPy_BezTriple type. It is + the destructor function. +****************************************************************************/ +static void BezTripleDeAlloc( BPy_BezTriple * self ) { + + if( self->own_memory) + MEM_freeN( self->beztriple ); + PyObject_DEL( self ); } -static PyObject *BezTriple_getPoints( C_BezTriple * self ) +static PyObject *BezTriple_getPoints( BPy_BezTriple * self ) { struct BezTriple *bezt = self->beztriple; PyObject *l = PyList_New( 0 ); @@ -175,7 +207,7 @@ static PyObject *BezTriple_getPoints( C_BezTriple * self ) * each point consists of a list of x,y,z float values. */ -static PyObject *BezTriple_getTriple( C_BezTriple * self ) +static PyObject *BezTriple_getTriple( BPy_BezTriple * self ) { int i; struct BezTriple *bezt = self->beztriple; @@ -194,7 +226,7 @@ static PyObject *BezTriple_getTriple( C_BezTriple * self ) } -static PyObject *BezTriple_setPoints( C_BezTriple * self, PyObject * args ) +static PyObject *BezTriple_setPoints( BPy_BezTriple * self, PyObject * args ) { int i; @@ -245,26 +277,30 @@ static PyObject *BezTriple_setPoints( C_BezTriple * self, PyObject * args ) /*****************************************************************************/ /* Function: BezTripleGetAttr */ -/* Description: This is a callback function for the C_BezTriple type. It */ -/* taccesses C_BezTriple "member variables" and methods. */ +/* Description: This is a callback function for the BPy_BezTriple type. It */ +/* taccesses BPy_BezTriple "member variables" and methods. */ /*****************************************************************************/ -static PyObject *BezTripleGetAttr( C_BezTriple * self, char *name ) +static PyObject *BezTripleGetAttr( BPy_BezTriple * self, char *name ) { if( strcmp( name, "pt" ) == 0 ) return BezTriple_getPoints( self ); else if( strcmp( name, "vec" ) == 0 ) return BezTriple_getTriple( self ); + else if( strcmp( name, "tilt" ) == 0 ) + return PyFloat_FromDouble(self->beztriple->alfa); + else if( strcmp( name, "__members__" ) == 0 ) + return Py_BuildValue( "[s,s,s]", "pt", "vec", "tilt" ); /* look for default methods */ - return Py_FindMethod( C_BezTriple_methods, ( PyObject * ) self, name ); + return Py_FindMethod( BPy_BezTriple_methods, ( PyObject * ) self, name ); } /*****************************************************************************/ /* Function: BezTripleSetAttr */ -/* Description: This is a callback function for the C_BezTriple type. It */ +/* Description: This is a callback function for the BPy_BezTriple type. It */ /* sets BezTriple Data attributes (member variables). */ /*****************************************************************************/ -static int BezTripleSetAttr( C_BezTriple * self, char *name, PyObject * value ) +static int BezTripleSetAttr( BPy_BezTriple * self, char *name, PyObject * value ) { #if 0 /* @@ -278,6 +314,13 @@ static int BezTripleSetAttr( C_BezTriple * self, char *name, PyObject * value ) return 0; /* normal exit */ #endif + if( strcmp( name, "tilt" ) == 0 ) { + if (!PyFloat_Check( value ) ) + return EXPP_ReturnIntError( PyExc_TypeError, "expected a float" ); + + self->beztriple->alfa = (float)PyFloat_AsDouble( value ); + return 0; + } return ( EXPP_ReturnIntError( PyExc_AttributeError, "cannot set a read-only attribute" ) ); @@ -285,10 +328,10 @@ static int BezTripleSetAttr( C_BezTriple * self, char *name, PyObject * value ) /*****************************************************************************/ /* Function: BezTripleRepr */ -/* Description: This is a callback function for the C_BezTriple type. It */ +/* Description: This is a callback function for the BPy_BezTriple type. It */ /* builds a meaninful string to represent BezTriple objects. */ /*****************************************************************************/ -static PyObject *BezTripleRepr( C_BezTriple * self ) +static PyObject *BezTripleRepr( BPy_BezTriple * self ) { /* float vec[3][3]; float alfa; @@ -313,29 +356,75 @@ static PyObject *BezTripleRepr( C_BezTriple * self ) return PyString_FromString( str ); } + +/* + BezTriple_Str + display object as string. + equivalent to python str(o) +*/ + +static PyObject *BezTriple_Str( BPy_BezTriple * self ) +{ + BezTriple *p = self->beztriple; + +/* fixme: */ + return PyString_FromFormat( + "BezTriple (%f %f %f) (%f %f %f) (%f %f %f) alpha %f\n (%d %d) (%d %d) (%d %d) h1:%d h2:%d f1:%d f2:%d f3:%d hide:%d", + p->vec[0][0], p->vec[0][1], p->vec[0][2], + p->vec[1][0], p->vec[1][1], p->vec[1][2], + p->vec[2][0], p->vec[2][1], p->vec[2][2], + p->alfa, + p->s[0][0], p->s[0][1], + p->s[1][0], p->s[1][1], + p->s[2][0], p->s[1][1], + p->h1, p->h2, p->f1, + p->f2, p->f3, + p->hide ); + +} + + +/* + BezTriple_Init +*/ + +PyObject *BezTriple_Init( void ) +{ + PyObject *submodule; + + BezTriple_Type.ob_type = &PyType_Type; + + submodule = Py_InitModule3( "Blender.BezTriple", + M_BezTriple_methods, + M_BezTriple_doc ); + + return submodule; +} + /* Three Python BezTriple_Type helper functions needed by the Object module: */ -/*****************************************************************************/ -/* Function: BezTriple_CreatePyObject */ -/* Description: This function will create a new C_BezTriple from an existing */ -/* Blender ipo structure. */ -/*****************************************************************************/ +/**************************************************************************** + Function: BezTriple_CreatePyObject + Description: This function will create a new BPy_BezTriple from an existing + Blender ipo structure. +****************************************************************************/ PyObject *BezTriple_CreatePyObject( BezTriple * bzt ) { - C_BezTriple *pybeztriple; + BPy_BezTriple *pybeztriple; pybeztriple = - ( C_BezTriple * ) PyObject_NEW( C_BezTriple, &BezTriple_Type ); + ( BPy_BezTriple * ) PyObject_NEW( BPy_BezTriple, &BezTriple_Type ); if( !pybeztriple ) return EXPP_ReturnPyObjError( PyExc_MemoryError, - "couldn't create C_BezTriple object" ); + "couldn't create BPy_BezTriple object" ); pybeztriple->beztriple = bzt; return ( PyObject * ) pybeztriple; } + /*****************************************************************************/ /* Function: BezTriple_CheckPyObject */ /* Description: This function returns true when the given PyObject is of the */ @@ -353,5 +442,100 @@ int BezTriple_CheckPyObject( PyObject * pyobj ) /*****************************************************************************/ BezTriple *BezTriple_FromPyObject( PyObject * pyobj ) { - return ( ( C_BezTriple * ) pyobj )->beztriple; + return ( ( BPy_BezTriple * ) pyobj )->beztriple; +} + + +/* + Create a new BezTriple + input args is a sequence - either 3 or 9 floats +*/ + +PyObject *newBezTriple( PyObject *args) +{ + BPy_BezTriple *pybez = NULL; + int length; + float numbuf[9]; +/* + check input args: + sequence of nine floats - x,y,z for h1, pt, h2 + sequence of 3 floats - x,y,z for pt with zero len handles in AUTO mode +*/ + + /* do we have a sequence of the right length? */ + + if( ! PySequence_Check( args )) { + return ( EXPP_ReturnPyObjError( PyExc_AttributeError, + "expected better stuff")); + } + + length = PySequence_Length( args ); + if( length != 9 && length != 3 ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "wrong number of points"); + { + int i; + PyObject *pyo; + for( i = 0; i < length; i++) { + pyo = PySequence_GetItem( args, i ); + if( !pyo ) + return EXPP_ReturnPyObjError + ( PyExc_AttributeError, + "wrong number of points"); + if( !PyFloat_Check( pyo )) + return EXPP_ReturnPyObjError + ( PyExc_AttributeError, + "sequence item not number"); + + numbuf[i] = (float) PyFloat_AsDouble( pyo ); + Py_DECREF( pyo ); /* from GetItem() */ + } + } + + + /* create our bpy object */ + pybez = ( BPy_BezTriple* ) PyObject_New( BPy_BezTriple, + &BezTriple_Type ); + if( ! pybez ) + return EXPP_ReturnPyObjError( PyExc_MemoryError, + "PyObject_New failed"); + pybez->beztriple = MEM_callocN( sizeof( BezTriple ), "new bpytriple"); + /* check malloc */ + + pybez->own_memory = 1; /* we own it. must free later */ + + + switch( length ) { + case 9: { + int i,j; + int num = 0; + for( i = 0; i < 3; i++ ){ + for( j = 0; j < 3; j++){ + pybez->beztriple->vec[i][j] = numbuf[num ++]; + } + } + } + break; + case 3: { + int i; + int num = 0; + /* set h1, pt, and h2 to the same values. */ + for( i = 0; i < 3; i++ ) { + pybez->beztriple->vec[0][i] = numbuf[num]; + pybez->beztriple->vec[1][i] = numbuf[num]; + pybez->beztriple->vec[2][i] = numbuf[num]; + ++num; + } + } + break; + default: + /* we should not be here! */ + break; + } + + + pybez->beztriple->h1 = HD_AUTO; + pybez->beztriple->h2 = HD_AUTO; + + return ( PyObject* ) pybez; } diff --git a/source/blender/python/api2_2x/BezTriple.h b/source/blender/python/api2_2x/BezTriple.h index f865fa73646..b37ae84a37b 100644 --- a/source/blender/python/api2_2x/BezTriple.h +++ b/source/blender/python/api2_2x/BezTriple.h @@ -25,7 +25,7 @@ * * This is a new part of Blender. * - * Contributor(s): Jacques Guignot + * Contributor(s): Jacques Guignot, Stephen Swaney * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ @@ -36,14 +36,21 @@ #include <Python.h> #include <DNA_curve_types.h> -/*****************************************************************************/ -/* Python C_BezTriple structure definition: */ -/*****************************************************************************/ +extern PyTypeObject BezTriple_Type; + +/* type check macro */ +#define BPy_BezTriple_Check(o) \ + ( (o)->ob_type == &BezTriple_Type) + +/**************************************************************************** + Python BPy_BezTriple structure definition: +****************************************************************************/ typedef struct { PyObject_HEAD /* required python macro */ BezTriple * beztriple; -} C_BezTriple; + int own_memory; /* true == we own this memory and must delete. */ +} BPy_BezTriple; /* * prototypes @@ -52,5 +59,7 @@ typedef struct { PyObject *BezTriple_CreatePyObject( BezTriple * bzt ); int BezTriple_CheckPyObject( PyObject * pyobj ); BezTriple *BezTriple_FromPyObject( PyObject * pyobj ); +PyObject *newBezTriple( PyObject *args ); +PyObject *BezTriple_Init( void ); #endif /* EXPP_BEZTRIPLE_H */ diff --git a/source/blender/python/api2_2x/Blender.c b/source/blender/python/api2_2x/Blender.c index 140bee0468d..f0af546ae67 100644 --- a/source/blender/python/api2_2x/Blender.c +++ b/source/blender/python/api2_2x/Blender.c @@ -803,8 +803,8 @@ void M_Blender_Init( void ) PyDict_SetItemString( dict, "Mathutils", Mathutils_Init( ) ); PyDict_SetItemString( dict, "Library", Library_Init( ) ); PyDict_SetItemString( dict, "Sound", Sound_Init( ) ); - PyDict_SetItemString( dict, "CurNurb", CurNurb_Init( ) ); + PyDict_SetItemString( dict, "BezTriple", BezTriple_Init( ) ); PyModule_AddIntConstant( module, "TRUE", 1 ); PyModule_AddIntConstant( module, "FALSE", 0 ); diff --git a/source/blender/python/api2_2x/CurNurb.c b/source/blender/python/api2_2x/CurNurb.c index 7dcbf142737..ce31f348c9f 100644 --- a/source/blender/python/api2_2x/CurNurb.c +++ b/source/blender/python/api2_2x/CurNurb.c @@ -32,6 +32,7 @@ #include "Python.h" #include "DNA_curve_types.h" #include "BKE_curve.h" +#include "BDR_editcurve.h" /* for convertspline */ #include "MEM_guardedalloc.h" #include "gen_utils.h" @@ -52,8 +53,11 @@ static PyObject *CurNurb_getFlagU( BPy_CurNurb * self ); static PyObject *CurNurb_setFlagU( BPy_CurNurb * self, PyObject * args ); static PyObject *CurNurb_getFlagV( BPy_CurNurb * self ); static PyObject *CurNurb_setFlagV( BPy_CurNurb * self, PyObject * args ); +static PyObject *CurNurb_getType( BPy_CurNurb * self ); +static PyObject *CurNurb_setType( BPy_CurNurb * self, PyObject * args ); /* static PyObject* CurNurb_setXXX( BPy_CurNurb* self, PyObject* args ); */ PyObject *CurNurb_getPoint( BPy_CurNurb * self, int index ); +static int CurNurb_setPoint( BPy_CurNurb * self, int index, PyObject * ob ); static int CurNurb_length( PyInstanceObject * inst ); static PyObject *CurNurb_getIter( BPy_CurNurb * self ); static PyObject *CurNurb_iterNext( BPy_CurNurb * self ); @@ -61,6 +65,7 @@ PyObject *CurNurb_append( BPy_CurNurb * self, PyObject * args ); PyObject *CurNurb_pointAtIndex( Nurb * nurb, int index ); static PyObject *CurNurb_isNurb( BPy_CurNurb * self ); static PyObject *CurNurb_isCyclic( BPy_CurNurb * self ); +static PyObject *CurNurb_dump( BPy_CurNurb * self ); char M_CurNurb_doc[] = "CurNurb"; @@ -117,16 +122,21 @@ static PyMethodDef BPy_CurNurb_methods[] = { "( index ) - set flagV and recalculate the knots (0: uniform, 1: endpoints, 2: bezier)"}, {"getFlagV", ( PyCFunction ) CurNurb_getFlagV, METH_NOARGS, "( ) - get flagV of the knots"}, + {"setType", ( PyCFunction ) CurNurb_setType, METH_VARARGS, + "( type ) - change the type of the curve (Poly: 0, Bezier: 1, NURBS: 4)"}, + {"getType", ( PyCFunction ) CurNurb_getType, METH_NOARGS, + "( ) - get the type of the curve (Poly: 0, Bezier: 1, NURBS: 4)"}, {"append", ( PyCFunction ) CurNurb_append, METH_VARARGS, "( point ) - add a new point. arg is BezTriple or list of x,y,z,w floats"}, {"isNurb", ( PyCFunction ) CurNurb_isNurb, METH_NOARGS, "( ) - boolean function tests if this spline is type nurb or bezier"}, {"isCyclic", ( PyCFunction ) CurNurb_isCyclic, METH_NOARGS, "( ) - boolean function tests if this spline is cyclic (closed) or not (open)"}, + {"dump", ( PyCFunction ) CurNurb_dump, METH_NOARGS, + "( ) - dumps Nurb data)"}, {NULL, NULL, 0, NULL} }; - /* * methods for CurNurb as sequece */ @@ -137,7 +147,7 @@ static PySequenceMethods CurNurb_as_sequence = { ( intargfunc ) 0, /* sq_repeat */ ( intargfunc ) CurNurb_getPoint, /* sq_item */ ( intintargfunc ) 0, /* sq_slice */ - 0, /* sq_ass_item */ + ( intobjargproc ) CurNurb_setPoint, /* sq_ass_item */ 0, /* sq_ass_slice */ ( objobjproc ) 0, /* sq_contains */ 0, @@ -261,6 +271,12 @@ static PyObject *CurNurb_getAttr( BPy_CurNurb * self, char *name ) else if( strcmp( name, "flagV" ) == 0 ) attr = CurNurb_getFlagV( self ); + else if( strcmp( name, "type" ) == 0 ) + attr = CurNurb_getType( self ); + + else if( strcmp( name, "__members__" ) == 0 ) + attr = Py_BuildValue( "[s,s,s,s,s]", "mat_index", "points", "flagU", "flagV", "type" ); + if( !attr ) return EXPP_ReturnPyObjError( PyExc_MemoryError, "couldn't create PyObject" ); @@ -292,11 +308,16 @@ static int CurNurb_setAttr( BPy_CurNurb * self, char *name, PyObject * value ) if( strcmp( name, "mat_index" ) == 0 ) error = CurNurb_setMatIndex( self, valtuple ); + else if( strcmp( name, "flagU" ) == 0 ) error = CurNurb_setFlagU( self, valtuple ); + else if( strcmp( name, "flagV" ) == 0 ) error = CurNurb_setFlagV( self, valtuple ); + else if( strcmp( name, "type" ) == 0 ) + error = CurNurb_setType( self, valtuple ); + else { /* error - no match for name */ Py_DECREF( valtuple ); @@ -368,6 +389,45 @@ static PyObject *M_CurNurb_New( PyObject * self, PyObject * args ) } +/* + * Curve.getType + */ +static PyObject *CurNurb_getType( BPy_CurNurb * self ) +{ + /* type is on 3 first bits only */ + return PyInt_FromLong( self->nurb->type & 7 ); +} + +/* + * Curve.setType + * + * Convert the curve using Blender's convertspline fonction + */ +static PyObject *CurNurb_setType( BPy_CurNurb * self, PyObject * args ) +{ + Nurb *nurb = self->nurb; + int type; + + /* parameter type checking */ + if( !PyArg_ParseTuple( args, "i", &type ) ) + return EXPP_ReturnPyObjError + ( PyExc_TypeError, "expected integer argument" ); + + /* parameter value checking */ + if (type != CU_POLY && + type != CU_BEZIER && + type != CU_NURBS) + return EXPP_ReturnPyObjError + ( PyExc_ValueError, "expected integer argument" ); + + /* convert and raise error if impossible */ + if (convertspline(type, nurb)) + return EXPP_ReturnPyObjError + ( PyExc_ValueError, "Conversion Impossible" ); + + return EXPP_incr_ret( Py_None ); +} + /* @@ -384,10 +444,10 @@ PyObject *CurNurb_append( BPy_CurNurb * self, PyObject * args ) } - /* * CurNurb_appendPointToNurb - * this is a non-bpy utility func to add a point to a given nurb + * this is a non-bpy utility func to add a point to a given nurb. + * notice the first arg is Nurb*. */ PyObject *CurNurb_appendPointToNurb( Nurb * nurb, PyObject * args ) @@ -396,19 +456,37 @@ PyObject *CurNurb_appendPointToNurb( Nurb * nurb, PyObject * args ) int i; int size; PyObject *pyOb; - int npoints; + int npoints = nurb->pntsu; /* do we have a list of four floats or a BezTriple? */ if( !PyArg_ParseTuple( args, "O", &pyOb )) - return( EXPP_ReturnPyObjError + return EXPP_ReturnPyObjError ( PyExc_RuntimeError, - "Internal error parsing arguments" ) ); + "Internal error parsing arguments" ); + + - if( BezTriple_CheckPyObject( pyOb ) ) { + /* if curve is empty, adjust type depending on input type */ + if (nurb->bezt==NULL && nurb->bp==NULL) { + if (BezTriple_CheckPyObject( pyOb )) + nurb->type |= CU_BEZIER; + else if (PySequence_Check( pyOb )) + nurb->type |= CU_NURBS; + else + return( EXPP_ReturnPyObjError( PyExc_TypeError, + "Expected a BezTriple or a Sequence of 4 (or 5) floats" ) ); + } + + + + if ((nurb->type & 7)==CU_BEZIER) { BezTriple *tmp; - npoints = nurb->pntsu; + + if( !BezTriple_CheckPyObject( pyOb ) ) + return( EXPP_ReturnPyObjError( PyExc_TypeError, + "Expected a BezTriple\n" ) ); /* printf("\ndbg: got a BezTriple\n"); */ tmp = nurb->bezt; /* save old points */ @@ -430,12 +508,12 @@ PyObject *CurNurb_appendPointToNurb( Nurb * nurb, PyObject * args ) memcpy( nurb->bezt + npoints, BezTriple_FromPyObject( pyOb ), sizeof( BezTriple ) ); - } else if( PySequence_Check( pyOb ) ) { + } + else if( PySequence_Check( pyOb ) ) { size = PySequence_Size( pyOb ); /* printf("\ndbg: got a sequence of size %d\n", size ); */ - if( size == 4 ) { + if( size == 4 || size == 5 ) { BPoint *tmp; - npoints = nurb->pntsu; tmp = nurb->bp; /* save old pts */ @@ -465,6 +543,13 @@ PyObject *CurNurb_appendPointToNurb( Nurb * nurb, PyObject * args ) } + if (size == 5) { + nurb->bp[npoints].alfa = (float)PyFloat_AsDouble( PySequence_GetItem( pyOb, 4 ) ); + } + else { + nurb->bp[npoints].alfa = 0.0f; + } + makeknots( nurb, 1, nurb->flagu >> 1 ); } else if( size == 3 ) { /* 3 xyz coords */ @@ -474,8 +559,8 @@ PyObject *CurNurb_appendPointToNurb( Nurb * nurb, PyObject * args ) } else { /* bail with error */ - return ( EXPP_ReturnPyObjError - ( PyExc_AttributeError, "expected better stuff" ) ); + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected a sequence of 4 (or optionaly 5) floats\n" ); } @@ -727,7 +812,6 @@ static int CurNurb_length( PyInstanceObject * inst ) PyObject *CurNurb_getPoint( BPy_CurNurb * self, int index ) { - PyObject *pyo; Nurb *myNurb; int npoints; @@ -739,19 +823,89 @@ PyObject *CurNurb_getPoint( BPy_CurNurb * self, int index ) /* DELETED: bail if index < 0 */ /* actually, this check is not needed since python treats */ /* negative indices as starting from the right end of a sequence */ + /* + THAT IS WRONG, when passing a negative index, python adjusts it to be positive + BUT it can still overflow in the negatives if the index is too small. + For example, list[-6] when list contains 5 items means index = -1 in here. + (theeth) + */ /* bail if no Nurbs in Curve */ if( npoints == 0 ) return ( EXPP_ReturnPyObjError( PyExc_IndexError, "no points in this CurNurb" ) ); - if( index >= npoints ) /* out of range! */ + /* check index limits */ + if( index >= npoints || index < 0 ) return ( EXPP_ReturnPyObjError( PyExc_IndexError, "index out of range" ) ); - pyo = CurNurb_pointAtIndex( myNurb, index ); + return CurNurb_pointAtIndex( myNurb, index ); +} + +/* + * CurNurb_setPoint + * modifies the Nth point in a Nurb + * this is one of the tp_as_sequence methods, hence the int N argument. + * it is called via the [] = operator, not as a usual instance method. + */ +static int CurNurb_setPoint( BPy_CurNurb * self, int index, PyObject * pyOb ) +{ + Nurb *nurb = self->nurb; + int size; - return ( PyObject * ) pyo; + /* check index limits */ + if( index < 0 || index >= nurb->pntsu ) + return EXPP_ReturnIntError( PyExc_IndexError, + "array assignment index out of range\n" ); + + + /* branch by curve type */ + if ((nurb->type & 7)==CU_BEZIER) { /* BEZIER */ + /* check parameter type */ + if( !BezTriple_CheckPyObject( pyOb ) ) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected a BezTriple\n" ); + + /* copy bezier in array */ + memcpy( nurb->bezt + index, + BezTriple_FromPyObject( pyOb ), sizeof( BezTriple ) ); + + return 0; /* finished correctly */ + } + else { /* NURBS or POLY */ + int i; + + /* check parameter type */ + if (!PySequence_Check( pyOb )) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected a list of 4 (or optionaly 5 if the curve is 3D) floats\n" ); + + size = PySequence_Size( pyOb ); + + /* check sequence size */ + if( size != 4 && size != 5 ) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected a list of 4 (or optionaly 5 if the curve is 3D) floats\n" ); + + /* copy x, y, z, w */ + for( i = 0; i < 4; ++i ) { + float tmpx = + ( float ) PyFloat_AsDouble + ( PySequence_GetItem( pyOb, i ) ); + nurb->bp[index].vec[i] = tmpx; + + } + + if (size == 5) { /* set tilt, if present */ + nurb->bp[index].alfa = (float)PyFloat_AsDouble( PySequence_GetItem( pyOb, 4 ) ); + } + else { /* if not, set default */ + nurb->bp[index].alfa = 0.0f; + } + + return 0; /* finished correctly */ + } } @@ -765,15 +919,23 @@ PyObject *CurNurb_pointAtIndex( Nurb * nurb, int index ) if( nurb->bp ) { /* we have a nurb curve */ int i; - pyo = PyList_New( 4 ); + + /* add Tilt only if curve is 3D */ + if (nurb->flag & CU_3D) + pyo = PyList_New( 5 ); + else + pyo = PyList_New( 4 ); for( i = 0; i < 4; i++ ) { PyList_SetItem( pyo, i, PyFloat_FromDouble( nurb->bp[index]. vec[i] ) ); - } + /* add Tilt only if curve is 3D */ + if (nurb->flag & CU_3D) + PyList_SetItem( pyo, 4, PyFloat_FromDouble( nurb->bp[index].alfa ) ); + } else if( nurb->bezt ) { /* we have a bezier */ /* if an error occurs, we just pass it on */ pyo = BezTriple_CreatePyObject( &( nurb->bezt[index] ) ); @@ -804,3 +966,76 @@ PyObject *CurNurb_Init( void ) M_CurNurb_doc ); return ( submodule ); } + + +/* + dump nurb +*/ + +PyObject *CurNurb_dump( BPy_CurNurb * self ) +{ + BPoint *bp = NULL; + BezTriple *bezt = NULL; + Nurb *nurb = self->nurb; + int npoints = 0; + + if( ! self->nurb ){ /* bail on error */ + printf("\n no Nurb in this CurNurb"); + Py_RETURN_NONE; + } + + printf(" type: %d, mat_nr: %d hide: %d flag: %d", + nurb->type, nurb->mat_nr, nurb->hide, nurb->flag); + printf("\n pntsu: %d, pntsv: %d, resolu: %d resolv: %d", + nurb->pntsu, nurb->pntsv, nurb->resolu, nurb->resolv ); + printf("\n orderu: %d orderv: %d", nurb->orderu, nurb->orderv ); + printf("\n flagu: %d flagv: %d", + nurb->flagu, nurb->flagv ); + + npoints = nurb->pntsu; + + if( nurb->bp ) { /* we have a BPoint */ + int n; + for( n = 0, bp = nurb->bp; + n < npoints; + n++, bp++ ) + { + /* vec[4] */ + printf( "\ncoords[%d]: ", n); + { + int i; + for( i = 0; i < 4; i++){ + printf("%10.3f ", bp->vec[i] ); + } + } + + /* alfa, s[2] */ + printf("\n alpha: %5.2f s: %d %d ", + bp->alfa, bp->s[0], bp->s[1] ); + /* f1, hide */ + printf(" f1 %d hide %d", bp->f1, bp->hide ); + printf("\n"); + } + } + else { /* we have a BezTriple */ + int n; + for( n = 0, bezt = nurb->bezt; + n < npoints; + n++, bezt++ ) + { + int i, j; + printf("\npoint %d: ", n); + for( i = 0; i < 3; i++ ) { + printf("\nvec[%i] ",i ); + for( j = 0; j < 3; j++ ) { + printf(" %5.2f ", bezt->vec[i][j] ); + } + } + + + } + printf("\n"); + } + + Py_RETURN_NONE; +} diff --git a/source/blender/python/api2_2x/Curve.c b/source/blender/python/api2_2x/Curve.c index 70a4200383d..7e5d8541478 100644 --- a/source/blender/python/api2_2x/Curve.c +++ b/source/blender/python/api2_2x/Curve.c @@ -77,6 +77,7 @@ static PyObject *M_Curve_Get( PyObject * self, PyObject * args ); /*****************************************************************************/ /* Python BPy_Curve instance methods declarations: */ /*****************************************************************************/ + PyObject *Curve_getName( BPy_Curve * self ); PyObject *Curve_setName( BPy_Curve * self, PyObject * args ); static PyObject *Curve_getPathLen( BPy_Curve * self ); @@ -121,7 +122,7 @@ static PyObject *Curve_setBevOb( BPy_Curve * self, PyObject * args ); static PyObject *Curve_getIter( BPy_Curve * self ); static PyObject *Curve_iterNext( BPy_Curve * self ); -static PyObject *Curve_update( BPy_Curve * self ); + PyObject *Curve_getNurb( BPy_Curve * self, int n ); static int Curve_length( PyInstanceObject * inst ); void update_displists( void *data ); @@ -476,6 +477,8 @@ PyObject *Curve_setName( BPy_Curve * self, PyObject * args ) PyOS_snprintf( buf, sizeof( buf ), "%s", name ); rename_id( &self->curve->id, buf ); /* proper way in Blender */ + Curve_update( self ); + Py_INCREF( Py_None ); return Py_None; } @@ -1187,6 +1190,12 @@ static PyObject *Curve_appendPoint( BPy_Curve * self, PyObject * args ) } +/**** + appendNurb( new_point ) + create a new nurb in the Curve and add the point param to it. + returns a refernce to the newly created nurb. +*****/ + static PyObject *Curve_appendNurb( BPy_Curve * self, PyObject * args ) { Nurb *nurb_ptr = self->curve->nurb.first; @@ -1210,8 +1219,11 @@ static PyObject *Curve_appendNurb( BPy_Curve * self, PyObject * args ) if( CurNurb_appendPointToNurb( new_nurb, args ) ) { *pptr = new_nurb; - new_nurb->resolu = 12; - new_nurb->resolv = 12; + new_nurb->resolu = self->curve->resolu; + new_nurb->resolv = self->curve->resolv; + new_nurb->hide = 0; + new_nurb->flag = 1; + if( new_nurb->bezt ) { /* do setup for bezt */ new_nurb->type = CU_BEZIER; @@ -1220,6 +1232,7 @@ static PyObject *Curve_appendNurb( BPy_Curve * self, PyObject * args ) new_nurb->bezt->f1 = 1; new_nurb->bezt->f2 = 1; new_nurb->bezt->f3 = 1; + new_nurb->bezt->hide = 0; /* calchandlesNurb( new_nurb ); */ } else { /* set up bp */ new_nurb->pntsv = 1; @@ -1228,6 +1241,7 @@ static PyObject *Curve_appendNurb( BPy_Curve * self, PyObject * args ) new_nurb->flagu = 0; new_nurb->flagv = 0; new_nurb->bp->f1 = 0; + new_nurb->bp->hide = 0; new_nurb->knotsu = 0; /*makenots( new_nurb, 1, new_nurb->flagu >> 1); */ } @@ -1237,7 +1251,7 @@ static PyObject *Curve_appendNurb( BPy_Curve * self, PyObject * args ) return NULL; /* with PyErr already set */ } - return EXPP_incr_ret( Py_None ); + return CurNurb_CreatePyObject( new_nurb ); } @@ -1247,10 +1261,10 @@ static PyObject *Curve_appendNurb( BPy_Curve * self, PyObject * args ) * used. after messing with control points */ -static PyObject *Curve_update( BPy_Curve * self ) +PyObject *Curve_update( BPy_Curve * self ) { -/* update_displists( ( void * ) self->curve ); */ - freedisplist( &self->curve->disp ); +/* update_displists( ( void * ) self->curve ); */ + freedisplist( &self->curve->disp ); Py_INCREF( Py_None ); return Py_None; diff --git a/source/blender/python/api2_2x/Curve.h b/source/blender/python/api2_2x/Curve.h index 4aad089ace3..31a1fdfd9aa 100644 --- a/source/blender/python/api2_2x/Curve.h +++ b/source/blender/python/api2_2x/Curve.h @@ -56,6 +56,7 @@ PyObject *Curve_Init( void ); PyObject *Curve_CreatePyObject( struct Curve * curve ); int Curve_CheckPyObject( PyObject * py_obj ); struct Curve *Curve_FromPyObject( PyObject * py_obj ); +PyObject *Curve_update( BPy_Curve * self ); PyObject *Curve_getName( BPy_Curve * self ); PyObject *Curve_setName( BPy_Curve * self, PyObject * args ); diff --git a/source/blender/python/api2_2x/doc/Curve.py b/source/blender/python/api2_2x/doc/Curve.py index a123ad1416b..b708ec7fc4b 100644 --- a/source/blender/python/api2_2x/doc/Curve.py +++ b/source/blender/python/api2_2x/doc/Curve.py @@ -394,16 +394,36 @@ class CurNurb: @cvar flagU: The CurNurb knot flag U (0: uniform, 1: endpoints, 2: bezier) @cvar flagV: The CurNurb knot flag V (0: uniform, 1: endpoints, 2: bezier) + @cvar type: The type of the curve (Poly: 0, Bezier: 1, NURBS: 4) """ + + def __setitem__( n, point ): + """ + Replace the Nth point in the curve. The type of the argument must match the type of the curve. List of 4 floats (optional 5th float is the tilt value in radians) for Nurbs or BezTriple for Bezier. + @rtype: PyNone + @return: PyNone + @type n: integer + @param n: the index of the element to replace + @type point: BezTriple or list of 4 floats (optional 5th float is the tilt value in radians) + @param point: the point that will replace the one in the curve. The point can be either a BezTriple type or a list of 4 floats in x,y,z,w (optionally tilt in radians as 5th value) format for a Nurb curve. + """ + def __getitem__( n ): + """ + Get the Nth element in the curve. For Bezier curves, that element is a BezTriple. For the rest (Poly and Nurbs), it is a list of 5 floats: x, y, z, weight, tilt (in radians). NOTE 1: This element element is independant on the curve, modifying it will not affect the curve. NOTE 2: Each successive call returns a new object. + @rtype: BezTriple (Bezier Curve) or List of 5 floats [x, y, z, w, t] for Poly or Nurbs + @return: The Nth element in the curve + @type n: integer + @param n: the index of the element to return + """ def append( new_point ): """ - Appends a new point to a curve. This method appends points to both Bezier and Nurb curves. The type of the argument must match the type of the curve. An empty curve will assume the type of the first appended point. + Appends a new point to a curve. This method appends points to both Bezier and Nurb curves. The type of the argument must match the type of the curve. List of 4 floats (optional 5th float is the tilt value in radians) for Nurbs or BezTriple for Bezier. @rtype: PyNone @return: PyNone - @type new_point: BezTriple or list of 4 floats - @param new_point: the new point to be appended to the curve. The new point can be either a BezTriple type or a list of 4 floats in x,y,z,w format for a Nurb curve. + @type new_point: BezTriple or list of 4 floats (optional 5th float is the tilt value in radians) + @param new_point: the new point to be appended to the curve. The new point can be either a BezTriple type or a list of 4 floats in x,y,z,w (optionally tilt in radians as 5th value) format for a Nurb curve. """ def setMatIndex( index ): @@ -467,3 +487,19 @@ class CurNurb: @rtype: PyNone @return: PyNone """ + + def getType(): + """ + Get the type of the curve + @rtype: integer + @return: 0 - Poly, 1 - Bezier, 4 - NURBS + """ + + def getType( value ): + """ + Set the type of the curve and converts the curve to its new type if needed + @type value: integer + @param value: CurNurb type flag (0 - Poly, 1 - Bezier, 4 - NURBS) + @rtype: PyNone + @return: PyNone + """ diff --git a/source/blender/python/api2_2x/modules.h b/source/blender/python/api2_2x/modules.h index a9f7d703199..fc8eb444925 100644 --- a/source/blender/python/api2_2x/modules.h +++ b/source/blender/python/api2_2x/modules.h @@ -45,6 +45,7 @@ Their *_Init() method declarations are hacked in down below. #include "Armature.h" +#include "BezTriple.h" #include "BGL.h" #include "Blender.h" #include "Camera.h" |