[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [21073] branches/blender2.5/blender/source : PyAPI Mathutils Vector callbacks, referencing other PyObjects rather then thin wrapping vectors which is crash prone .

Campbell Barton ideasman42 at gmail.com
Mon Jun 22 06:26:49 CEST 2009


Revision: 21073
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=21073
Author:   campbellbarton
Date:     2009-06-22 06:26:48 +0200 (Mon, 22 Jun 2009)

Log Message:
-----------
PyAPI Mathutils Vector callbacks, referencing other PyObjects rather then thin wrapping vectors which is crash prone.

in short, vectors can work as if they are thin wrapped but not crash blender if the original data is removed.

* RNA vector's return Mathutils vector types.
* BGE vectors for GameObject's localPosition, worldPosition, localPosition, localScale, worldScale, localInertia.
* Comment USE_MATHUTILS define to disable returning vectors.

Example...

* 2.49... *
 loc = gameOb.worldPosition
 loc[1] = 0
 gameOb.worldPosition = loc

* With vectors... *
 gameOb.worldPosition[1] = 0


* But this wont crash... *
 loc = gameOb.worldPosition
 gameOb.endObject()
 loc[1] = 0 # will raise an error that the objects removed.

This breaks games which assume return values are lists.

Will add this to eulers, matrix and quaternion types later.

Modified Paths:
--------------
    branches/blender2.5/blender/source/blender/python/generic/Geometry.c
    branches/blender2.5/blender/source/blender/python/generic/Mathutils.c
    branches/blender2.5/blender/source/blender/python/generic/Mathutils.h
    branches/blender2.5/blender/source/blender/python/generic/matrix.c
    branches/blender2.5/blender/source/blender/python/generic/quat.c
    branches/blender2.5/blender/source/blender/python/generic/vector.c
    branches/blender2.5/blender/source/blender/python/generic/vector.h
    branches/blender2.5/blender/source/blender/python/intern/bpy_rna.c
    branches/blender2.5/blender/source/blender/python/intern/bpy_util.c
    branches/blender2.5/blender/source/gameengine/Expressions/PyObjectPlus.h
    branches/blender2.5/blender/source/gameengine/Ketsji/KX_GameObject.cpp
    branches/blender2.5/blender/source/gameengine/Ketsji/KX_GameObject.h
    branches/blender2.5/blender/source/gameengine/Ketsji/KX_PythonInitTypes.cpp

Modified: branches/blender2.5/blender/source/blender/python/generic/Geometry.c
===================================================================
--- branches/blender2.5/blender/source/blender/python/generic/Geometry.c	2009-06-22 04:23:06 UTC (rev 21072)
+++ branches/blender2.5/blender/source/blender/python/generic/Geometry.c	2009-06-22 04:26:48 UTC (rev 21073)
@@ -164,6 +164,10 @@
 			for( index = 0; index<len_polypoints; ++index, fp+=3) {
 				polyVec= PySequence_GetItem( polyLine, index );
 				if(VectorObject_Check(polyVec)) {
+					
+					if(!Vector_ReadCallback((VectorObject *)polyVec))
+						ls_error= 1;
+					
 					fp[0] = ((VectorObject *)polyVec)->vec[0];
 					fp[1] = ((VectorObject *)polyVec)->vec[1];
 					if( ((VectorObject *)polyVec)->size > 2 )
@@ -234,6 +238,9 @@
 		return NULL;
 	}
 	
+	if(!Vector_ReadCallback(line_a1) || !Vector_ReadCallback(line_a2) || !Vector_ReadCallback(line_b1) || !Vector_ReadCallback(line_b2))
+		return NULL;
+	
 	a1x= line_a1->vec[0];
 	a1y= line_a1->vec[1];
 	a2x= line_a2->vec[0];
@@ -330,6 +337,10 @@
 		PyErr_SetString( PyExc_TypeError, "expected 3 vector types\n" );
 		return NULL;
 	}
+	
+	if(!Vector_ReadCallback(pt) || !Vector_ReadCallback(line_1) || !Vector_ReadCallback(line_2))
+		return NULL;
+	
 	/* accept 2d verts */
 	if (pt->size==3) { VECCOPY(pt_in, pt->vec);}
 	else { pt_in[2]=0.0;	VECCOPY2D(pt_in, pt->vec) }
@@ -363,6 +374,9 @@
 		return NULL;
 	}
 	
+	if(!Vector_ReadCallback(pt_vec) || !Vector_ReadCallback(tri_p1) || !Vector_ReadCallback(tri_p2) || !Vector_ReadCallback(tri_p3))
+		return NULL;
+	
 	return PyLong_FromLong(IsectPT2Df(pt_vec->vec, tri_p1->vec, tri_p2->vec, tri_p3->vec));
 }
 
@@ -381,6 +395,9 @@
 		return NULL;
 	}
 	
+	if(!Vector_ReadCallback(pt_vec) || !Vector_ReadCallback(quad_p1) || !Vector_ReadCallback(quad_p2) || !Vector_ReadCallback(quad_p3) || !Vector_ReadCallback(quad_p4))
+		return NULL;
+	
 	return PyLong_FromLong(IsectPQ2Df(pt_vec->vec, quad_p1->vec, quad_p2->vec, quad_p3->vec, quad_p4->vec));
 }
 
@@ -500,6 +517,9 @@
 		return NULL;
 	}
 	
+	if(!Vector_ReadCallback(vec_k1) || !Vector_ReadCallback(vec_h1) || !Vector_ReadCallback(vec_k2) || !Vector_ReadCallback(vec_h2))
+		return NULL;
+	
 	dims= MAX4(vec_k1->size, vec_h1->size, vec_h2->size, vec_k2->size);
 	
 	for(i=0; i < vec_k1->size; i++) k1[i]= vec_k1->vec[i];

Modified: branches/blender2.5/blender/source/blender/python/generic/Mathutils.c
===================================================================
--- branches/blender2.5/blender/source/blender/python/generic/Mathutils.c	2009-06-22 04:23:06 UTC (rev 21072)
+++ branches/blender2.5/blender/source/blender/python/generic/Mathutils.c	2009-06-22 04:26:48 UTC (rev 21073)
@@ -141,77 +141,6 @@
 }
 
 //-----------------------------METHODS----------------------------
-//----------------column_vector_multiplication (internal)---------
-//COLUMN VECTOR Multiplication (Matrix X Vector)
-// [1][2][3]   [a]
-// [4][5][6] * [b]
-// [7][8][9]   [c]
-//vector/matrix multiplication IS NOT COMMUTATIVE!!!!
-PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject* vec)
-{
-	float vecNew[4], vecCopy[4];
-	double dot = 0.0f;
-	int x, y, z = 0;
-
-	if(mat->rowSize != vec->size){
-		if(mat->rowSize == 4 && vec->size != 3){
-			PyErr_SetString(PyExc_AttributeError, "matrix * vector: matrix row size and vector size must be the same");
-			return NULL;
-		}else{
-			vecCopy[3] = 1.0f;
-		}
-	}
-
-	for(x = 0; x < vec->size; x++){
-		vecCopy[x] = vec->vec[x];
-		}
-
-	for(x = 0; x < mat->rowSize; x++) {
-		for(y = 0; y < mat->colSize; y++) {
-			dot += mat->matrix[x][y] * vecCopy[y];
-		}
-		vecNew[z++] = (float)dot;
-		dot = 0.0f;
-	}
-	return newVectorObject(vecNew, vec->size, Py_NEW);
-}
-
-//-----------------row_vector_multiplication (internal)-----------
-//ROW VECTOR Multiplication - Vector X Matrix
-//[x][y][z] *  [1][2][3]
-//             [4][5][6]
-//             [7][8][9]
-//vector/matrix multiplication IS NOT COMMUTATIVE!!!!
-PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat)
-{
-	float vecNew[4], vecCopy[4];
-	double dot = 0.0f;
-	int x, y, z = 0, vec_size = vec->size;
-
-	if(mat->colSize != vec_size){
-		if(mat->rowSize == 4 && vec_size != 3){
-			PyErr_SetString(PyExc_AttributeError, "vector * matrix: matrix column size and the vector size must be the same");
-			return NULL;
-		}else{
-			vecCopy[3] = 1.0f;
-		}
-	}
-	
-	for(x = 0; x < vec_size; x++){
-		vecCopy[x] = vec->vec[x];
-	}
-
-	//muliplication
-	for(x = 0; x < mat->colSize; x++) {
-		for(y = 0; y < mat->rowSize; y++) {
-			dot += mat->matrix[y][x] * vecCopy[y];
-		}
-		vecNew[z++] = (float)dot;
-		dot = 0.0f;
-	}
-	return newVectorObject(vecNew, vec_size, Py_NEW);
-}
-
 //-----------------quat_rotation (internal)-----------
 //This function multiplies a vector/point * quat or vice versa
 //to rotate the point/vector by the quaternion
@@ -226,6 +155,10 @@
 		quat = (QuaternionObject*)arg1;
 		if(VectorObject_Check(arg2)){
 			vec = (VectorObject*)arg2;
+			
+			if(!Vector_ReadCallback(vec))
+				return NULL;
+			
 			rot[0] = quat->quat[0]*quat->quat[0]*vec->vec[0] + 2*quat->quat[2]*quat->quat[0]*vec->vec[2] - 
 				2*quat->quat[3]*quat->quat[0]*vec->vec[1] + quat->quat[1]*quat->quat[1]*vec->vec[0] + 
 				2*quat->quat[2]*quat->quat[1]*vec->vec[1] + 2*quat->quat[3]*quat->quat[1]*vec->vec[2] - 
@@ -242,6 +175,10 @@
 		}
 	}else if(VectorObject_Check(arg1)){
 		vec = (VectorObject*)arg1;
+		
+		if(!Vector_ReadCallback(vec))
+			return NULL;
+		
 		if(QuaternionObject_Check(arg2)){
 			quat = (QuaternionObject*)arg2;
 			rot[0] = quat->quat[0]*quat->quat[0]*vec->vec[0] + 2*quat->quat[2]*quat->quat[0]*vec->vec[2] - 
@@ -308,6 +245,9 @@
 	if(vec1->size != vec2->size)
 		goto AttributeError1; //bad sizes
 
+	if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2))
+		return NULL;
+	
 	//since size is the same....
 	size = vec1->size;
 
@@ -353,6 +293,9 @@
 		PyErr_SetString(PyExc_AttributeError, "Mathutils.MidpointVecs(): expects (2) vector objects of the same size\n");
 		return NULL;
 	}
+	
+	if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2))
+		return NULL;
 
 	for(x = 0; x < vec1->size; x++) {
 		vec[x] = 0.5f * (vec1->vec[x] + vec2->vec[x]);
@@ -377,6 +320,10 @@
 		return NULL;
 	}
 
+	if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2))
+		return NULL;
+
+	
 	//since they are the same size...
 	size = vec1->size;
 
@@ -439,6 +386,10 @@
 			PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): the arbitrary axis must be a 3D vector\n");
 			return NULL;
 		}
+		
+		if(!Vector_ReadCallback(vec))
+			return NULL;
+		
 	}
 	//convert to radians
 	angle = angle * (float) (Py_PI / 180);
@@ -538,6 +489,10 @@
 		PyErr_SetString(PyExc_TypeError, "Mathutils.TranslationMatrix(): vector must be 3D or 4D\n");
 		return NULL;
 	}
+	
+	if(!Vector_ReadCallback(vec))
+		return NULL;
+	
 	//create a identity matrix and add translation
 	Mat4One((float(*)[4]) mat);
 	mat[12] = vec->vec[0];
@@ -570,6 +525,10 @@
 			PyErr_SetString(PyExc_AttributeError, "Mathutils.ScaleMatrix(): please use 2D vectors when scaling in 2D\n");
 			return NULL;
 		}
+		
+		if(!Vector_ReadCallback(vec))
+			return NULL;
+		
 	}
 	if(vec == NULL) {	//scaling along axis
 		if(matSize == 2) {
@@ -645,6 +604,10 @@
 			PyErr_SetString(PyExc_AttributeError, "Mathutils.OrthoProjectionMatrix(): please use 2D vectors when scaling in 2D\n");
 			return NULL;
 		}
+		
+		if(!Vector_ReadCallback(vec))
+			return NULL;
+		
 	}
 	if(vec == NULL) {	//ortho projection onto cardinal plane
 		if(((strcmp(plane, "x") == 0)
@@ -891,6 +854,9 @@
 		return NULL;
 	}
 
+	if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2) || !Vector_ReadCallback(vec3) || !Vector_ReadCallback(ray) || !Vector_ReadCallback(ray_off))
+		return NULL;
+	
 	VECCOPY(v1, vec1->vec);
 	VECCOPY(v2, vec2->vec);
 	VECCOPY(v3, vec3->vec);
@@ -959,6 +925,10 @@
 		PyErr_SetString( PyExc_TypeError,"vectors must be of the same size\n" );
 		return NULL;
 	}
+	
+	if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2) || !Vector_ReadCallback(vec3) || !Vector_ReadCallback(vec4))
+		return NULL;
+	
 	if( vec1->size == 3 || vec1->size == 2) {
 		int result;
 		
@@ -1029,6 +999,10 @@
 		PyErr_SetString( PyExc_TypeError, "only 3D vectors\n" );
 		return NULL;
 	}
+	
+	if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2) || !Vector_ReadCallback(vec3) || !Vector_ReadCallback(vec4))
+		return NULL;
+	
 	VECCOPY(v1, vec1->vec);
 	VECCOPY(v2, vec2->vec);
 	VECCOPY(v3, vec3->vec);
@@ -1073,6 +1047,9 @@
 		PyErr_SetString( PyExc_TypeError, "only 3D vectors\n" );
 		return NULL;
 	}
+	
+	if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2) || !Vector_ReadCallback(vec3))
+		return NULL;
 
 	VECCOPY(v1, vec1->vec);
 	VECCOPY(v2, vec2->vec);
@@ -1105,6 +1082,9 @@
 		PyErr_SetString( PyExc_TypeError, "vectors must be of the same size\n" );
 		return NULL;
 	}
+	
+	if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2) || !Vector_ReadCallback(vec3))
+		return NULL;
 
 	if (vec1->size == 3) {
 		VECCOPY(v1, vec1->vec);
@@ -1154,8 +1134,8 @@
 }
 /*---------------------- EXPP_VectorsAreEqual -------------------------
   Builds on EXPP_FloatsAreEqual to test vectors */
-int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps){
-
+int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps)
+{
 	int x;
 	for (x=0; x< size; x++){
 		if (EXPP_FloatsAreEqual(vecA[x], vecB[x], floatSteps) == 0)
@@ -1165,6 +1145,81 @@
 }
 
 
+/* Mathutils Callbacks */
 
-//#######################################################################
-//#############################DEPRECATED################################
+/* for mathutils internal use only, eventually should re-alloc but to start with we only have a few users */
+Mathutils_Callback *mathutils_callbacks[8] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
+
+int Mathutils_RegisterCallback(Mathutils_Callback *cb)
+{
+	int i;
+	
+	/* find the first free slot */
+	for(i= 0; mathutils_callbacks[i]; i++) {
+		if(mathutils_callbacks[i]==cb) /* alredy registered? */
+			return i;
+	}
+	
+	mathutils_callbacks[i] = cb;
+	return i;
+}
+
+int Vector_ReadCallback(VectorObject *self) {
+	if(self->user) {
+		Mathutils_Callback *cb= mathutils_callbacks[self->callback_type];
+		if(cb->get(self->user, self->subtype, self->vec)) {
+			return 1;
+		}
+		else {
+			PyErr_SetString(PyExc_SystemError, "Vector user has become invalid");
+			return 0;
+		}
+	}
+	
+	return 1; /* no user continue silently */

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list