Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Swaney <sswaney@centurytel.net>2004-07-22 01:01:15 +0400
committerStephen Swaney <sswaney@centurytel.net>2004-07-22 01:01:15 +0400
commitbce2c02fdd6ebaf88ffc0950e87de96b0b65377f (patch)
tree708d01a564f56cb729d8e536c8de15c70f7349dd /source/blender/python/api2_2x/CurNurb.c
parent1c5302e68b47c03fd60ab5edefb4a16d6294b7a7 (diff)
New Curve method Curve.appendPoint( numcurve, newpoint ) to add
points to a Curve. New supporting module CurNurb to provide access to the curves in a Curve and their associated points. Curve module now supports Python iterator and sequence protocols. This allows typical python programming idioms using 'for' statement and the [] operator. # example 1 for curve in a_curve: for point in curve: print point #example 2 curnurb = a_curve[0] curnurb.append( [1,1,1,1] ) Still under construction. Epydoc will follow.
Diffstat (limited to 'source/blender/python/api2_2x/CurNurb.c')
-rw-r--r--source/blender/python/api2_2x/CurNurb.c686
1 files changed, 686 insertions, 0 deletions
diff --git a/source/blender/python/api2_2x/CurNurb.c b/source/blender/python/api2_2x/CurNurb.c
new file mode 100644
index 00000000000..cb233c4e5ee
--- /dev/null
+++ b/source/blender/python/api2_2x/CurNurb.c
@@ -0,0 +1,686 @@
+/*
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * This is a new part of Blender.
+ *
+ * Contributor(s):
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include "Python.h"
+#include "DNA_curve_types.h"
+#include "BKE_curve.h"
+#include "MEM_guardedalloc.h"
+#include "bpy_types.h"
+#include "modules.h"
+#include "gen_utils.h"
+#include "CurNurb.h"
+
+
+/*-------------------------------------------------------------
+
+stuff in this section should be placed in bpy_types.h
+
+-----------------------------------------------------------*/
+
+
+/*
+ * forward declarations go here
+ */
+
+
+extern PyMethodDef BPy_CurNurb_methods[];
+PyObject *CurNurb_CreatePyObject( Nurb * blen_nurb );
+static PyObject *CurNurb_setMatIndex( BPy_CurNurb * self, PyObject * args );
+static PyObject *CurNurb_getMatIndex( BPy_CurNurb * self );
+/* static PyObject* CurNurb_setXXX( BPy_CurNurb* self, PyObject* args ); */
+PyObject* CurNurb_getPoint( BPy_CurNurb* self, int index );
+static int CurNurb_length( PyInstanceObject *inst);
+static PyObject *CurNurb_getIter (BPy_CurNurb * self);
+static PyObject *CurNurb_iterNext (BPy_CurNurb * self);
+PyObject* CurNurb_append( BPy_CurNurb* self, PyObject* args );
+PyObject* CurNurb_pointAtIndex( Nurb* nurb, int index );
+static PyObject *CurNurb_isNurb( BPy_CurNurb* self );
+
+char M_CurNurb_doc[] = "CurNurb";
+
+
+/*
+ CurNurb_Type callback function prototypes:
+*/
+
+static void CurNurb_dealloc( BPy_CurNurb * self );
+static int CurNurb_compare( BPy_CurNurb * a, BPy_CurNurb * b );
+static PyObject *CurNurb_getAttr( BPy_CurNurb * self, char *name );
+static int CurNurb_setAttr( BPy_CurNurb * self, char *name, PyObject * v );
+static PyObject *CurNurb_repr( BPy_CurNurb * self );
+
+
+
+
+void CurNurb_dealloc( BPy_CurNurb * self )
+{
+ PyObject_DEL( self );
+}
+
+
+
+static PyObject *CurNurb_getAttr( BPy_CurNurb * self, char *name )
+{
+ PyObject *attr = Py_None;
+
+ if( strcmp( name, "mat_index" ) == 0 )
+ attr = PyInt_FromLong( self->nurb->mat_nr );
+
+ else if( strcmp( name, "points" ) == 0 )
+ attr = PyInt_FromLong( self->nurb->pntsu );
+
+ if( !attr )
+ return EXPP_ReturnPyObjError( PyExc_MemoryError,
+ "couldn't create PyObject" );
+
+ /* member attribute found, return it */
+ if( attr != Py_None )
+ return attr;
+
+ /* not an attribute, search the methods table */
+ return Py_FindMethod( BPy_CurNurb_methods, ( PyObject * ) self, name );
+}
+
+
+/*
+ setattr
+*/
+
+static int CurNurb_setAttr( BPy_CurNurb * self, char *name, PyObject * value )
+{
+ PyObject *valtuple;
+ PyObject *error = NULL;
+
+ /* make a tuple to pass to our type methods */
+ valtuple = Py_BuildValue( "(O)", value );
+
+ if( !valtuple )
+ return EXPP_ReturnIntError( PyExc_MemoryError,
+ "CurNurb.setAttr: cannot create pytuple" );
+
+ if( strcmp( name, "mat_index" ) == 0 )
+ error = CurNurb_setMatIndex( self, valtuple );
+
+ else { /* error - no match for name */
+ Py_DECREF( valtuple );
+
+ if( ( strcmp( name, "ZZZZ" ) == 0 ) || /* user tried to change a */
+ ( strcmp( name, "ZZZZ" ) == 0 ) ) /* constant dict type ... */
+ return EXPP_ReturnIntError( PyExc_AttributeError,
+ "constant dictionary -- cannot be changed" );
+ else
+ return EXPP_ReturnIntError( PyExc_KeyError,
+ "attribute not found" );
+ }
+
+
+ Py_DECREF( valtuple ); /* since it is not being returned */
+ if( error != Py_None )
+ return -1;
+
+ Py_DECREF( Py_None );
+ return 0; /* normal exit */
+}
+
+/*
+ compare
+ in this case, we consider two CurNurbs equal, if they point to the same
+ blender data.
+*/
+
+static int CurNurb_compare( BPy_CurNurb * a, BPy_CurNurb * b )
+{
+ Nurb *pa = a->nurb;
+ Nurb *pb = b->nurb;
+
+ return ( pa == pb ) ? 0 : -1;
+}
+
+
+/*
+ factory method to create a BPy_CurNurb from a Blender Nurb
+*/
+
+PyObject *CurNurb_CreatePyObject( Nurb * blen_nurb )
+{
+ BPy_CurNurb *pyNurb;
+
+ pyNurb = ( BPy_CurNurb * ) PyObject_NEW( BPy_CurNurb, &CurNurb_Type );
+
+ if( !pyNurb )
+ return EXPP_ReturnPyObjError( PyExc_MemoryError,
+ "could not create BPy_CurNurb PyObject" );
+
+ pyNurb->nurb = blen_nurb;
+ return ( PyObject * ) pyNurb;
+}
+
+
+/*
+ * CurNurb_repr
+ */
+static PyObject *CurNurb_repr( BPy_CurNurb * self )
+{ /* used by 'repr' */
+
+ return PyString_FromFormat( "[CurNurb \"%d\"]", self->nurb->type );
+}
+
+
+static PyObject *M_CurNurb_New( PyObject * self, PyObject * args )
+{
+ return ( PyObject * ) 0;
+
+}
+
+
+
+/*
+ * CurNurb_append( point )
+ * append a new point to a nurb curve.
+ * arg is BezTriple or list of xyzw floats
+ */
+
+PyObject* CurNurb_append( BPy_CurNurb* self, PyObject* args )
+{
+ Nurb* nurb = self->nurb;
+
+ return CurNurb_appendPointToNurb( nurb, args );
+}
+
+
+
+/*
+ * CurNurb_appendPointToNurb
+ * this is a non-bpy utility func to add a point to a given nurb
+ */
+
+PyObject* CurNurb_appendPointToNurb( Nurb* nurb, PyObject* args )
+{
+
+ int i;
+ int size;
+ PyObject* pyOb;
+ int npoints;
+
+ /*
+ do we have a list of four floats or a BezTriple?
+ */
+ PyArg_ParseTuple( args, "O", &pyOb );
+
+ if( BezTriple_CheckPyObject( pyOb )){
+ BezTriple* tmp;
+ npoints = nurb->pntsu;
+
+/* printf("\ndbg: got a BezTriple\n"); */
+ tmp = nurb->bezt; /* save old points */
+ nurb->bezt = (BezTriple*)MEM_mallocN (
+ sizeof(BezTriple) * (npoints + 1), "CurNurb_append2");
+
+ if( ! nurb->bezt )
+ return( EXPP_ReturnPyObjError
+ (PyExc_MemoryError, "allocation failed"));
+
+ /* copy old points to new */
+ memmove( nurb->bezt, tmp, sizeof( BezTriple) * npoints );
+ MEM_freeN( tmp );
+ nurb->pntsu++;
+ /* add new point to end of list */
+ memcpy( nurb->bezt + npoints,
+ BezTriple_FromPyObject( pyOb),
+ sizeof( BezTriple));
+
+ } else if( PySequence_Check( pyOb )) {
+ size = PySequence_Size( pyOb );
+/* printf("\ndbg: got a sequence of size %d\n", size ); */
+ if( size == 4 ) {
+ BPoint* tmp;
+ npoints = nurb->pntsu;
+
+ tmp = nurb->bp; /* save old pts */
+
+ nurb->bp =(BPoint*)MEM_mallocN ( sizeof (BPoint) * (npoints + 1),
+ "CurNurb_append1");
+ if( ! nurb->bp )
+ return( EXPP_ReturnPyObjError
+ (PyExc_MemoryError, "allocation failed"));
+
+ memmove( nurb->bp, tmp, sizeof(BPoint) * npoints );
+ MEM_freeN( tmp );
+
+ ++nurb->pntsu;
+ /* initialize new BPoint from old */
+ memcpy( nurb->bp + npoints, nurb->bp, sizeof (BPoint));
+
+ for( i=0; i < 4; ++i){
+ float tmpx =
+ (float) PyFloat_AsDouble
+ ( PySequence_GetItem ( pyOb, i));
+ nurb->bp[npoints].vec[i] = tmpx;
+
+ }
+
+ makeknots(nurb, 1, nurb->flagu >> 1);
+
+ }else if( size == 3 ){ /* 3 xyz coords */
+ printf("\nNot Yet Implemented!\n");
+
+ }
+
+ } else {
+ /* bail with error */
+ return ( EXPP_ReturnPyObjError
+ ( PyExc_AttributeError,
+ "expected better stuff" ) );
+
+ }
+
+ return (EXPP_incr_ret( Py_None ));
+}
+
+
+/*
+ * CurNurb_setMatIndex
+ *
+ * set index into material list
+ */
+
+static PyObject *CurNurb_setMatIndex( BPy_CurNurb * self, PyObject * args )
+{
+ int index;
+
+ if( !PyArg_ParseTuple( args, "i", &( index ) ) )
+ return ( EXPP_ReturnPyObjError
+ ( PyExc_AttributeError,
+ "expected integer argument" ) );
+
+ /* fixme: some range checking would be nice! */
+ self->nurb->mat_nr = index;
+
+ Py_INCREF( Py_None );
+ return Py_None;
+}
+
+/*
+ * CurNurb_getMatIndex
+ *
+ * returns index into material list
+ */
+
+static PyObject *CurNurb_getMatIndex( BPy_CurNurb * self )
+{
+ PyObject *index = PyInt_FromLong( ( long ) self->nurb->mat_nr );
+
+ if( index )
+ return index;
+
+ return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
+ "could not get material index" ) );
+}
+
+
+/*
+ * CurNurb_getIter
+ *
+ * create an iterator for our CurNurb.
+ * this iterator returns the points for this CurNurb.
+ */
+
+static PyObject *CurNurb_getIter (BPy_CurNurb * self)
+{
+ self->bp = self->nurb->bp;
+ self->bezt = self->nurb->bezt;
+ self->atEnd = 0;
+ self->nextPoint = 0;
+
+ /* set exhausted flag if both bp and bezt are zero */
+ if( (!self->bp) && (!self->bezt))
+ self->atEnd = 1;
+
+ Py_INCREF( self );
+ return (PyObject*) self;
+}
+
+
+
+static PyObject *CurNurb_iterNext( BPy_CurNurb * self )
+{
+ PyObject *po; /* return value */
+ Nurb *pnurb = self->nurb;
+ int npoints = pnurb->pntsu;
+
+ /* are we at end already? */
+ if( self->atEnd )
+ return ( EXPP_ReturnPyObjError( PyExc_StopIteration,
+ "iterator at end" ) );
+
+ if( self->nextPoint < npoints ){
+
+ po = CurNurb_pointAtIndex( self->nurb, self->nextPoint);
+ self->nextPoint++;
+
+ return po;
+
+ }
+ else{
+ self->atEnd = 1; /* set flag true */
+ }
+
+ return( EXPP_ReturnPyObjError( PyExc_StopIteration,
+ "iterator at end" ) );
+}
+
+
+
+/*
+ * CurNurb_isNurb()
+ * test whether spline nurb or bezier
+ */
+
+static PyObject *CurNurb_isNurb( BPy_CurNurb* self )
+{
+ /* NOTE: a Nurb has bp and bezt pointers
+ * depending on type.
+ * It is possible both are NULL if no points exist.
+ * in that case, we return False
+ */
+
+ if( self->nurb->bp ){
+ Py_INCREF( Py_True );
+ return Py_True;
+ }
+ else{
+ Py_INCREF( Py_False );
+ return( Py_False );
+ }
+}
+
+
+/*
+ table of module methods
+ these are the equivalent of class or static methods.
+ you do not need an object instance to call one.
+
+*/
+
+static PyMethodDef M_CurNurb_methods[] = {
+/* name, method, flags, doc_string */
+ {"New", ( PyCFunction ) M_CurNurb_New, METH_VARARGS | METH_KEYWORDS,
+ " () - doc string"},
+/* {"Get", (PyCFunction) M_CurNurb_method, METH_NOARGS, " () - doc string"}, */
+/* {"method", (PyCFunction) M_CurNurb_method, METH_NOARGS, " () - doc string"}, */
+
+ {NULL, NULL, 0, NULL}
+};
+
+
+
+/*
+ * method table
+ * table of instance methods
+ * these methods are invoked on an instance of the type.
+*/
+
+static PyMethodDef BPy_CurNurb_methods[] = {
+/* name, method, flags, doc */
+/* {"method", (PyCFunction) CurNurb_method, METH_NOARGS, " () - doc string"} */
+ {"setMatIndex", ( PyCFunction ) CurNurb_setMatIndex, METH_VARARGS,
+ "( index ) - set index into materials list"},
+ {"getMatIndex", ( PyCFunction ) CurNurb_getMatIndex, METH_NOARGS,
+ "( ) - get current material index"},
+ {"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"},
+ {NULL, NULL, 0, NULL}
+};
+
+
+/*
+ * methods for CurNurb as sequece
+ */
+
+static PySequenceMethods CurNurb_as_sequence = {
+ (inquiry)CurNurb_length, /* sq_length */
+ (binaryfunc) 0, /* sq_concat */
+ (intargfunc) 0, /* sq_repeat */
+ (intargfunc) CurNurb_getPoint, /* sq_item */
+ (intintargfunc) 0, /* sq_slice */
+ 0, /* sq_ass_item */
+ 0, /* sq_ass_slice */
+ (objobjproc) 0, /* sq_contains */
+ 0,
+ 0
+};
+
+
+
+/*
+ Object Type definition
+ full blown 2.3 struct
+*/
+
+PyTypeObject CurNurb_Type = {
+ PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /* ob_size */
+ /* For printing, in format "<module>.<name>" */
+ "CurNurb", /* char *tp_name; */
+ sizeof( CurNurb_Type ), /* int tp_basicsize, */
+ 0, /* tp_itemsize; For allocation */
+
+ /* Methods to implement standard operations */
+
+ ( destructor ) CurNurb_dealloc, /* destructor tp_dealloc; */
+ 0, /* printfunc tp_print; */
+ ( getattrfunc ) CurNurb_getAttr, /* getattrfunc tp_getattr; */
+ ( setattrfunc ) CurNurb_setAttr, /* setattrfunc tp_setattr; */
+ ( cmpfunc ) CurNurb_compare, /* cmpfunc tp_compare; */
+ ( reprfunc ) CurNurb_repr, /* reprfunc tp_repr; */
+
+ /* Method suites for standard classes */
+
+ 0, /* PyNumberMethods *tp_as_number; */
+ &CurNurb_as_sequence, /* PySequenceMethods *tp_as_sequence; */
+ 0, /* PyMappingMethods *tp_as_mapping; */
+
+ /* More standard operations (here for binary compatibility) */
+
+ 0, /* hashfunc tp_hash; */
+ 0, /* ternaryfunc tp_call; */
+ 0, /* reprfunc tp_str; */
+ 0, /* getattrofunc tp_getattro; */
+ 0, /* setattrofunc tp_setattro; */
+
+ /* Functions to access object as input/output buffer */
+ 0, /* PyBufferProcs *tp_as_buffer; */
+
+ /*** Flags to define presence of optional/expanded features ***/
+ Py_TPFLAGS_DEFAULT, /* long tp_flags; */
+
+ 0, /* char *tp_doc; Documentation string */
+ /*** Assigned meaning in release 2.0 ***/
+ /* call function for all accessible objects */
+ 0, /* traverseproc tp_traverse; */
+
+ /* delete references to contained objects */
+ 0, /* inquiry tp_clear; */
+
+ /*** Assigned meaning in release 2.1 ***/
+ /*** rich comparisons ***/
+ 0, /* richcmpfunc tp_richcompare; */
+
+ /*** weak reference enabler ***/
+ 0, /* long tp_weaklistoffset; */
+
+ /*** Added in release 2.2 ***/
+ /* Iterators */
+ (getiterfunc) CurNurb_getIter, /* getiterfunc tp_iter; */
+ (iternextfunc) CurNurb_iterNext, /* iternextfunc tp_iternext; */
+
+ /*** Attribute descriptor and subclassing stuff ***/
+ BPy_CurNurb_methods, /* struct PyMethodDef *tp_methods; */
+ 0, /* struct PyMemberDef *tp_members; */
+ 0, /* struct PyGetSetDef *tp_getset; */
+ 0, /* struct _typeobject *tp_base; */
+ 0, /* PyObject *tp_dict; */
+ 0, /* descrgetfunc tp_descr_get; */
+ 0, /* descrsetfunc tp_descr_set; */
+ 0, /* long tp_dictoffset; */
+ 0, /* initproc tp_init; */
+ 0, /* allocfunc tp_alloc; */
+ 0, /* newfunc tp_new; */
+ /* Low-level free-memory routine */
+ 0, /* freefunc tp_free; */
+ /* For PyObject_IS_GC */
+ 0, /* inquiry tp_is_gc; */
+ 0, /* PyObject *tp_bases; */
+ /* method resolution order */
+ 0, /* PyObject *tp_mro; */
+ 0, /* PyObject *tp_cache; */
+ 0, /* PyObject *tp_subclasses; */
+ 0, /* PyObject *tp_weaklist; */
+ 0
+};
+
+
+/*
+ * CurNurb_length
+ * returns the number of points in a Nurb
+ * this is a tp_as_sequence method, not a regular instance method.
+ */
+
+static int CurNurb_length( PyInstanceObject *inst)
+{
+ Nurb* nurb;
+ int len;
+
+ if( CurNurb_CheckPyObject( (PyObject*)inst ) ) {
+ nurb = ((BPy_CurNurb*) inst)->nurb;
+ len = nurb->pntsu;
+ return len;
+ }
+
+ return EXPP_ReturnIntError( PyExc_RuntimeError,
+ "arg is not a BPy_CurNurb" );
+
+}
+
+
+/*
+ * CurNurb_getPoint
+ * returns 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.
+ */
+
+PyObject* CurNurb_getPoint( BPy_CurNurb* self, int index )
+{
+ PyObject *pyo;
+ Nurb* myNurb;
+
+ int npoints;
+
+ /* for convenince */
+ myNurb = self->nurb;
+ npoints = myNurb->pntsu;
+
+ /* 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 */
+
+ /* 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! */
+ return( EXPP_ReturnPyObjError( PyExc_IndexError,
+ "index out of range"));
+
+ pyo = CurNurb_pointAtIndex( myNurb, index );
+
+ // handle bezt case AND bp case
+
+
+
+
+ return (PyObject*) pyo;
+
+}
+
+
+/*
+ * this is an internal routine. not callable directly from python
+ */
+
+PyObject* CurNurb_pointAtIndex( Nurb* nurb, int index )
+{
+ PyObject* pyo;
+
+ if( nurb->bp ){ /* we have a nurb curve */
+ int i;
+ pyo = PyList_New( 4 );
+
+ for( i = 0; i < 4; i++ ){
+ PyList_SetItem( pyo, i,
+ PyFloat_FromDouble( nurb->bp[index].vec[i] ));
+
+ }
+
+ }else if( nurb->bezt ) { /* we have a bezier */
+ /* if an error occurs, we just pass it on */
+ pyo = BezTriple_CreatePyObject( &( nurb->bezt[index] ) );
+
+ }
+ else /* something is horribly wrong */
+ /* neither bp or bezt is set && pntsu != 0 */
+ return( EXPP_ReturnPyObjError( PyExc_SystemError,
+ "inconsistant structure found"));
+
+
+ return( pyo );
+}
+
+
+int CurNurb_CheckPyObject( PyObject * py_obj )
+{
+ return ( py_obj->ob_type == &CurNurb_Type );
+}
+
+
+PyObject *CurNurb_Init (void)
+{
+ PyObject *submodule;
+
+ Curve_Type.ob_type = &PyType_Type;
+
+ submodule =
+ Py_InitModule3 ("Blender.CurNurb", M_CurNurb_methods, M_CurNurb_doc);
+ return (submodule);
+}