[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [11060] branches/pyapi_devel/source/ blender/python/api2_2x: PyAPI: added extra checks to mesh api ( some of these should be added to trunk & 2.44 stable)

Campbell Barton cbarton at metavr.com
Tue Jun 26 10:06:32 CEST 2007


Revision: 11060
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=11060
Author:   campbellbarton
Date:     2007-06-26 10:06:32 +0200 (Tue, 26 Jun 2007)

Log Message:
-----------
PyAPI: added extra checks to mesh api (some of these should be added to trunk & 2.44 stable)
Added a PyObject to the vector struct, so a vector can reference an PyObject with an ID or a matrix.
added checks so that a wrapped vector will raise an error if the (ID) data it references is removed.

This means a scenes cursor (vector) complain if its used when the scenes deleted. before this would mess up memory.

removed checks for the creation of PyInts

Still need to make 

Modified Paths:
--------------
    branches/pyapi_devel/source/blender/python/api2_2x/Mesh.c
    branches/pyapi_devel/source/blender/python/api2_2x/vector.c
    branches/pyapi_devel/source/blender/python/api2_2x/vector.h

Modified: branches/pyapi_devel/source/blender/python/api2_2x/Mesh.c
===================================================================
--- branches/pyapi_devel/source/blender/python/api2_2x/Mesh.c	2007-06-26 04:28:23 UTC (rev 11059)
+++ branches/pyapi_devel/source/blender/python/api2_2x/Mesh.c	2007-06-26 08:06:32 UTC (rev 11060)
@@ -126,7 +126,13 @@
 static PyObject *MFace_CreatePyObject( BPy_Mesh * bpymesh, int i );
 static PyObject *MEdge_CreatePyObject( BPy_Mesh * bpymesh, int i );
 
+/* These checks are only needed if we allow users to remove meshes */
+// #define MESH_DEL_CHECK_PY(_mesh) if (!(_mesh)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "This mesh has been removed" ) )
+// #define MESH_DEL_CHECK_INT(_mesh) if (!(_mesh)) return ( EXPP_ReturnIntError( PyExc_RuntimeError, "This mesh has been removed" ) )
 
+#define MFACE_VERT_BADRANGE_CHECK(me, face) ((int)face->v1 >= me->totvert || (int)face->v2 >= me->totvert || (int)face->v3 >= me->totvert || (int)face->v4 >= me->totvert)
+#define MEDGE_VERT_BADRANGE_CHECK(me, edge) ((int)edge->v1 >= me->totvert || (int)edge->v2 >= me->totvert)
+
 /************************************************************************
  *
  * internal utilities
@@ -588,8 +594,11 @@
 static PyObject *MCol_getAttr( BPy_MCol * self, void *type )
 {
 	unsigned char param;
-	PyObject *attr;
-
+	
+	// MESH_DEL_CHECK_PY(self->bpymesh->mesh);
+	
+	/* TODO - Check the face was still there */
+	
 	switch( (long)type ) {
     case 'R':	/* these are backwards, but that how it works */
 		param = self->color->b;
@@ -612,12 +621,7 @@
 		}
 	}
 
-	attr = PyInt_FromLong( param );
-	if( attr )
-		return attr;
-
-	return EXPP_ReturnPyObjError( PyExc_RuntimeError,
-			"PyInt_FromLong() failed"); 
+	return PyInt_FromLong( param ); 
 }
 
 /*
@@ -627,7 +631,9 @@
 static int MCol_setAttr( BPy_MCol * self, PyObject * value, void * type )
 {
 	unsigned char *param;
-
+	
+	// MESH_DEL_CHECK_INT(self->bpymesh->mesh);
+	
 	switch( (long)type ) {
     case 'R':	/* these are backwards, but that how it works */
 		param = (unsigned char *)&self->color->b;
@@ -690,7 +696,9 @@
 static PyObject *MCol_item(BPy_MCol * self, int i)
 {
 	unsigned char param;
-	PyObject *attr;
+	
+	// MESH_DEL_CHECK_PY(self->bpymesh->mesh);
+	
 	switch (i) {
 	case 0:
 		param = self->color->b;
@@ -709,12 +717,7 @@
 			"vector[index] = x: assignment index out of range\n");
 	}
 	
-	attr = PyInt_FromLong( param );
-	if( attr )
-		return attr;
-
-	return EXPP_ReturnPyObjError( PyExc_RuntimeError,
-			"PyInt_FromLong() failed");
+	return PyInt_FromLong( param );
 }
 
 /*----------------------------object[]-------------------------
@@ -723,6 +726,8 @@
 {
 	unsigned char *param;
 	
+	// MESH_DEL_CHECK_INT(self->bpymesh->mesh);
+	
 	switch (i) {
 	case 0:
 		param = (unsigned char *)&self->color->b; /* reversed? why */
@@ -752,9 +757,13 @@
 
 static PyObject *MCol_repr( BPy_MCol * self )
 {
+	if (self->bpymesh->mesh) {
 	return PyString_FromFormat( "[MCol %d %d %d %d]",
 			(int)self->color->b, (int)self->color->g, 
-			(int)self->color->r, (int)self->color->a ); 
+			(int)self->color->r, (int)self->color->a );
+	} else {
+		return PyString_FromString( "[MCol <deleted>]" );
+	}
 }
 
 /*-----------------PROTCOL DECLARATIONS--------------------------*/
@@ -878,16 +887,15 @@
 
 static MVert * MVert_get_pointer( BPy_MVert * self )
 {
-	//if( BPy_MVert_Check( self ) ) {
+	if( BPy_MVert_Check( self ) ) {
 		if (!self->bpymesh->mesh || self->index >= ((Mesh *)(self->bpymesh->mesh))->totvert)
 			return (MVert *)EXPP_ReturnPyObjError( PyExc_RuntimeError,
 					"MVert is no longer valid" );
 		
-		return &((Mesh *)self->bpymesh->mesh)->mvert[self->index];
-	//}
-	/* TODO - pvert support */
-	//else
-	//	return (MVert *)self->data;
+		return &(self->bpymesh->mesh)->mvert[self->index];
+	} else {
+		return (MVert *)self->bpymesh;
+	}
 }
 
 /*
@@ -897,10 +905,10 @@
 static PyObject *MVert_getCoord( BPy_MVert * self )
 {
 	MVert *v;
-
+	
 	v = MVert_get_pointer( self );
 	if( !v )
-		return NULL;
+		return NULL; /* error is set */
 
 	return newVectorObject( v->co, 3, Py_WRAP, (BPy_GenericLib *)self->bpymesh );
 }
@@ -916,7 +924,7 @@
 
 	v = MVert_get_pointer( self );
 	if( !v )
-		return -1;
+		return -1; /* error is set */
 
 	if( !VectorObject_Check( value ) || value->size != 3 )
 		return EXPP_ReturnIntError( PyExc_TypeError,
@@ -934,18 +942,13 @@
 
 static PyObject *MVert_getIndex( BPy_MVert * self )
 {
-	PyObject *attr;
-
+	// MESH_DEL_CHECK_PY(self->bpymesh->mesh);
+	
 	if( self->index >= self->bpymesh->mesh->totvert )
 		return EXPP_ReturnPyObjError( PyExc_RuntimeError,
 				"MVert is no longer valid" );
 
-	attr = PyInt_FromLong( self->index );
-	if( attr )
-		return attr;
-
-	return EXPP_ReturnPyObjError( PyExc_RuntimeError,
-			"PyInt_FromLong() failed" );
+	return PyInt_FromLong( self->index );
 }
 
 
@@ -960,8 +963,7 @@
 	v = MVert_get_pointer( self );
 	
 	if (!v)
-		return EXPP_ReturnPyObjError( PyExc_RuntimeError,
-				"This mesh is no longer valid" );
+		return NULL; /* error is set */
 	
 	if( self->index >= self->bpymesh->mesh->totvert )
 		return EXPP_ReturnPyObjError( PyExc_RuntimeError,
@@ -983,8 +985,7 @@
 	v = MVert_get_pointer( self );
 
 	if (!v)
-		return EXPP_ReturnIntError( PyExc_RuntimeError,
-				"This mesh is no longer valid" );
+		return -1; /* error is set */
 	
 	if( self->index >= self->bpymesh->mesh->totvert )
 		return EXPP_ReturnIntError( PyExc_RuntimeError,
@@ -1007,7 +1008,7 @@
 
 	v = MVert_get_pointer( self );
 	if( !v )
-		return NULL;
+		return NULL; /* error set */
 
 	for( i = 0; i < 3; ++i )
 		no[i] = (float)(v->no[i] / 32767.0);
@@ -1026,7 +1027,7 @@
 	
 	v = MVert_get_pointer( self );
 	if( !v )
-		return -1;
+		return -1; /* error set */
 
 	if( !VectorObject_Check( value ) || value->size != 3 )
 		return EXPP_ReturnIntError( PyExc_TypeError,
@@ -1055,7 +1056,7 @@
 
 	v = MVert_get_pointer( self );
 	if( !v )
-		return NULL;
+		return NULL; /* error is set */
 
 	return EXPP_getBitfield( &v->flag, SELECT, 'b' );
 }
@@ -1094,7 +1095,11 @@
 static PyObject *MVert_getUVco( BPy_MVert *self )
 {
 	Mesh *me = self->bpymesh->mesh;
-
+	
+	if( !me )
+		return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+				"mesh has been removed" );
+	
 	if( !me->msticky )
 		return EXPP_ReturnPyObjError( PyExc_AttributeError,
 				"mesh has no 'sticky' coordinates" );
@@ -1123,7 +1128,7 @@
 	 */
 	if( !me )
 		return EXPP_ReturnIntError( PyExc_RuntimeError,
-				"This mesh is no longer valid" );
+				"This mesh has been removed" );
 	
 	if( !me->msticky )
 		return EXPP_ReturnIntError( PyExc_AttributeError,
@@ -1135,15 +1140,12 @@
 
 	if( VectorObject_Check( value ) ) {
 		VectorObject *vect = (VectorObject *)value;
-		if( vect->size != 2 )
-			return EXPP_ReturnIntError( PyExc_AttributeError,
-					"expected 2D vector" );
-		for( i = 0; i < vect->size; ++i )
+		for( i = 0; i < vect->size; ++i ) /* allow 3d vectors, just use the 2d part */
 			uvco[i] = vect->vec[i];
 	} else if( !PyArg_ParseTuple( value, "ff",
 				&uvco[0], &uvco[1] ) )
 		return EXPP_ReturnIntError( PyExc_TypeError,
-				"expected 2D vector" );
+				"expected 2D vector or a float pair" );
 
 	v = &me->msticky[self->index];
 
@@ -1226,11 +1228,12 @@
 {
 	char format[512];
 	char index[24];
-	MVert *v;
+	MVert *v = MVert_get_pointer( self );
 
-	v = MVert_get_pointer( self );
-	if( !v )
-		return NULL;
+	if( !v ) {
+		PyErr_Clear(); /* clear error from MFace_get_pointer */
+		return PyString_FromString( "[MVert <deleted>]");		
+	}
 
 	if( BPy_MVert_Check( self ) )
 		sprintf( index, "%d", self->index );
@@ -1717,7 +1720,7 @@
 				"MEM_callocN() failed" );
 
 	memcpy( newvert, vert, sizeof( MVert ) );
-	//obj->bpydata = newvert; // TODO - add support back.
+	obj->bpymesh = ( BPy_GenericLib *)newvert;
 	return (PyObject *)obj;
 }
 
@@ -1729,6 +1732,8 @@
 
 static int MVertSeq_len( BPy_MVertSeq * self )
 {
+	if (!self->bpymesh->mesh)
+		return 0;
 	return self->bpymesh->mesh->totvert;
 }
 
@@ -1738,6 +1743,8 @@
 
 static PyObject *MVertSeq_item( BPy_MVertSeq * self, int i )
 {
+	// MESH_DEL_CHECK_PY(self->bpymesh->mesh);
+		
 	if( i < 0 || i >= self->bpymesh->mesh->totvert )
 		return EXPP_ReturnPyObjError( PyExc_IndexError,
 					      "array index out of range" );
@@ -1759,12 +1766,14 @@
 	PyObject *list;
 	int i;
 
+	// MESH_DEL_CHECK_PY(self->bpymesh->mesh);
+	
 	/*
 	 * Python list slice operator returns empty list when asked for a slice
 	 * outside the list, or if indices are reversed (low > high).  Clamp
 	 * our input to do the same.
 	 */
-
+	
 	if( low < 0 ) low = 0;
 	if( high > self->bpymesh->mesh->totvert ) high = self->bpymesh->mesh->totvert;
 	if( low > high ) low = high;
@@ -1791,9 +1800,13 @@
 static int MVertSeq_assign_item( BPy_MVertSeq * self, int i,
 		BPy_MVert *v )
 {
-	MVert *dst = &self->bpymesh->mesh->mvert[i];
+	MVert *dst;
 	MVert *src;
-
+	
+	// MESH_DEL_CHECK_INT(self->bpymesh->mesh);
+	
+	dst = &self->bpymesh->mesh->mvert[i];
+	
 	if( !v )
 		return EXPP_ReturnIntError( PyExc_IndexError,
 					      "del() not supported" );
@@ -1804,8 +1817,8 @@
 
 	if( BPy_MVert_Check( v ) )
 		src = &((Mesh *)v->bpymesh->mesh)->mvert[v->index];
-	//else
-	//	src = v->data; /* TODO - add pvert support */
+	else
+		src = (MVert *)v->bpymesh;
 
 	memcpy( dst, src, sizeof(MVert) );
 	/* mesh_update( self->mesh );*/
@@ -1820,7 +1833,9 @@
 	if( !PyList_Check( args ) )
 		return EXPP_ReturnIntError( PyExc_IndexError,
 					      "can only assign lists of MVerts" );
-
+	
+	// MESH_DEL_CHECK_INT(self->bpymesh->mesh);
+	
 	len = PyList_Size( args );
 
 	/*
@@ -1891,6 +1906,8 @@
 
 static PyObject *MVertSeq_getIter( BPy_MVertSeq * self )
 {
+	// MESH_DEL_CHECK_PY(self->bpymesh->mesh);
+	
 	if (self->iter==-1) { /* iteration for this pyobject is not yet used, just return self */
 		self->iter = 0;
 		return EXPP_incr_ret ( (PyObject *) self );
@@ -1908,6 +1925,8 @@
 
 static PyObject *MVertSeq_nextIter( BPy_MVertSeq * self )
 {
+	// MESH_DEL_CHECK_PY(self->bpymesh->mesh);
+	
 	if( self->iter == self->bpymesh->mesh->totvert ) {
 		self->iter= -1; /* allow it to be used as an iterator again without creating a new BPy_MVertSeq */
 		return EXPP_ReturnPyObjError( PyExc_StopIteration,
@@ -1933,6 +1952,8 @@
 	CustomData vdata;
 	/* make sure we get a sequence of tuples of something */
 
+	// MESH_DEL_CHECK_PY(mesh);
+	
 	switch( PySequence_Size( args ) ) {
 	case 1:		/* better be a list or a tuple */
 		tmp = PyTuple_GET_ITEM( args, 0 );
@@ -2096,6 +2117,8 @@
 	Mesh *mesh = self->bpymesh->mesh;
 	MFace *tmpface;
 
+	// MESH_DEL_CHECK_PY(mesh);
+	
 	/*

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list