687 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			687 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|   | /*
 | ||
|  |  * $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); | ||
|  | } |