From 5dcf97c892eeaf99a66e10a3100ef1f8e7e774e4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 3 Oct 2006 16:07:48 +0000 Subject: moved vector objects to getseters, added in place operations. Vector_iadd vec1+=vec2 Vector_isub vec1-=vec2 Vector_imul vec1*=float or vec1*=mat Vector_idiv vec1/=float length is now writable vec.length= float --- source/blender/python/api2_2x/Mathutils.c | 18 +- source/blender/python/api2_2x/vector.c | 752 +++++++++++++++++++++--------- 2 files changed, 532 insertions(+), 238 deletions(-) (limited to 'source') diff --git a/source/blender/python/api2_2x/Mathutils.c b/source/blender/python/api2_2x/Mathutils.c index 0fe11ecda0d..524755bdc20 100644 --- a/source/blender/python/api2_2x/Mathutils.c +++ b/source/blender/python/api2_2x/Mathutils.c @@ -117,7 +117,11 @@ PyObject *Mathutils_Init(void) //seed the generator for the rand function BLI_srand((unsigned int) (PIL_check_seconds_timer() * 0x7FFFFFFF)); - + + /* needed for getseters */ + if( PyType_Ready( &vector_Type ) < 0 ) + return NULL; + submodule = Py_InitModule3("Blender.Mathutils", M_Mathutils_methods, M_Mathutils_doc); return (submodule); @@ -197,18 +201,18 @@ PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat) { float vecNew[4], vecCopy[4]; double dot = 0.0f; - int x, y, z = 0, size; + int x, y, z = 0, vec_size = vec->size; - if(mat->colSize != vec->size){ - if(mat->rowSize == 4 && vec->size != 3){ + if(mat->colSize != vec_size){ + if(mat->rowSize == 4 && vec_size != 3){ return EXPP_ReturnPyObjError(PyExc_AttributeError, "vector * matrix: matrix column size and the vector size must be the same"); }else{ vecCopy[3] = 1.0f; } } - size = vec->size; - for(x = 0; x < vec->size; x++){ + + for(x = 0; x < vec_size; x++){ vecCopy[x] = vec->vec[x]; } @@ -220,7 +224,7 @@ PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat) vecNew[z++] = (float)dot; dot = 0.0f; } - return newVectorObject(vecNew, size, Py_NEW); + return newVectorObject(vecNew, vec_size, Py_NEW); } //This is a helper for the point class PyObject *row_point_multiplication(PointObject* pt, MatrixObject * mat) diff --git a/source/blender/python/api2_2x/vector.c b/source/blender/python/api2_2x/vector.c index a3d703dfdc2..b0b76669e71 100644 --- a/source/blender/python/api2_2x/vector.c +++ b/source/blender/python/api2_2x/vector.c @@ -60,20 +60,21 @@ struct PyMethodDef Vector_methods[] = { {"__copy__", (PyCFunction) Vector_copy, METH_NOARGS, Vector_copy_doc}, {NULL, NULL, 0, NULL} }; + /*-----------------------------METHODS---------------------------- --------------------------Vector.toPoint()---------------------- create a new point object to represent this vector */ PyObject *Vector_toPoint(VectorObject * self) { float coord[3]; - int x; + int i; if(self->size < 2 || self->size > 3) { return EXPP_ReturnPyObjError(PyExc_AttributeError, "Vector.toPoint(): inappropriate vector size - expects 2d or 3d vector\n"); } - for(x = 0; x < self->size; x++){ - coord[x] = self->vec[x]; + for(i = 0; i < self->size; i++){ + coord[i] = self->vec[i]; } return newPointObject(coord, self->size, Py_NEW); @@ -82,9 +83,9 @@ PyObject *Vector_toPoint(VectorObject * self) set the vector data to 0,0,0 */ PyObject *Vector_Zero(VectorObject * self) { - int x; - for(x = 0; x < self->size; x++) { - self->vec[x] = 0.0f; + int i; + for(i = 0; i < self->size; i++) { + self->vec[i] = 0.0f; } return EXPP_incr_ret((PyObject*)self); } @@ -92,15 +93,15 @@ PyObject *Vector_Zero(VectorObject * self) normalize the vector data to a unit vector */ PyObject *Vector_Normalize(VectorObject * self) { - int x; + int i; float norm = 0.0f; - for(x = 0; x < self->size; x++) { - norm += self->vec[x] * self->vec[x]; + for(i = 0; i < self->size; i++) { + norm += self->vec[i] * self->vec[i]; } norm = (float) sqrt(norm); - for(x = 0; x < self->size; x++) { - self->vec[x] /= norm; + for(i = 0; i < self->size; i++) { + self->vec[i] /= norm; } return EXPP_incr_ret((PyObject*)self); } @@ -295,93 +296,13 @@ PyObject *Vector_copy(VectorObject * self) free the py_object */ static void Vector_dealloc(VectorObject * self) { - //Py_XDECREF(self->coerced_object); /*only free py_data*/ if(self->data.py_data){ PyMem_Free(self->data.py_data); } PyObject_DEL(self); } -/*----------------------------getattr()(internal) ---------------- - object.attribute access (get)*/ -static PyObject *Vector_getattr(VectorObject * self, char *name) -{ - int x; - double dot = 0.0f; - if(STREQ(name,"x")){ - return PyFloat_FromDouble(self->vec[0]); - }else if(STREQ(name, "y")){ - return PyFloat_FromDouble(self->vec[1]); - }else if(STREQ(name, "z")){ - if(self->size > 2){ - return PyFloat_FromDouble(self->vec[2]); - }else{ - return EXPP_ReturnPyObjError(PyExc_AttributeError, - "vector.z: error, cannot get this axis for a 2D vector\n"); - } - }else if(STREQ(name, "w")){ - if(self->size > 3){ - return PyFloat_FromDouble(self->vec[3]); - }else{ - return EXPP_ReturnPyObjError(PyExc_AttributeError, - "vector.w: error, cannot get this axis for a 3D vector\n"); - } - }else if(STREQ2(name, "length", "magnitude")) { - for(x = 0; x < self->size; x++){ - dot += (self->vec[x] * self->vec[x]); - } - return PyFloat_FromDouble(sqrt(dot)); - } - if(STREQ(name, "wrapped")){ - if(self->wrapped == Py_WRAP) - return EXPP_incr_ret((PyObject *)Py_True); - else - return EXPP_incr_ret((PyObject *)Py_False); - } - return Py_FindMethod(Vector_methods, (PyObject *) self, name); -} -/*----------------------------setattr()(internal) ---------------- - object.attribute access (set) */ -static int Vector_setattr(VectorObject * self, char *name, PyObject * v) -{ - PyObject *f = NULL; - - f = PyNumber_Float(v); - if(f == NULL) { /* parsed item not a number */ - return EXPP_ReturnIntError(PyExc_TypeError, - "vector.attribute = x: argument not a number\n"); - } - - if(STREQ(name,"x")){ - self->vec[0] = (float)PyFloat_AS_DOUBLE(f); - }else if(STREQ(name, "y")){ - self->vec[1] = (float)PyFloat_AS_DOUBLE(f); - }else if(STREQ(name, "z")){ - if(self->size > 2){ - self->vec[2] = (float)PyFloat_AS_DOUBLE(f); - }else{ - Py_DECREF(f); - return EXPP_ReturnIntError(PyExc_AttributeError, - "vector.z = x: error, cannot set this axis for a 2D vector\n"); - } - }else if(STREQ(name, "w")){ - if(self->size > 3){ - self->vec[3] = (float)PyFloat_AS_DOUBLE(f); - }else{ - Py_DECREF(f); - return EXPP_ReturnIntError(PyExc_AttributeError, - "vector.w = x: error, cannot set this axis for a 2D vector\n"); - } - }else{ - Py_DECREF(f); - return EXPP_ReturnIntError(PyExc_AttributeError, - "vector.attribute = x: unknown attribute\n"); - } - - Py_DECREF(f); - return 0; -} /*----------------------------print object (internal)------------- print the object to screen */ static PyObject *Vector_repr(VectorObject * self) @@ -425,23 +346,20 @@ static PyObject *Vector_item(VectorObject * self, int i) sequence accessor (set)*/ static int Vector_ass_item(VectorObject * self, int i, PyObject * ob) { - PyObject *f = NULL; - - f = PyNumber_Float(ob); - if(f == NULL) { /* parsed item not a number */ + + if(!(PyNumber_Check(ob))) { /* parsed item not a number */ return EXPP_ReturnIntError(PyExc_TypeError, "vector[index] = x: index argument not a number\n"); } if(i < 0 || i >= self->size){ - Py_DECREF(f); return EXPP_ReturnIntError(PyExc_IndexError, "vector[index] = x: assignment index out of range\n"); } - self->vec[i] = (float)PyFloat_AS_DOUBLE(f); - Py_DECREF(f); + self->vec[i] = (float)PyFloat_AsDouble(ob); return 0; } + /*----------------------------object[z:y]------------------------ sequence slice (get) */ static PyObject *Vector_slice(VectorObject * self, int begin, int end) @@ -468,7 +386,7 @@ static int Vector_ass_slice(VectorObject * self, int begin, int end, { int i, y, size = 0; float vec[4]; - PyObject *v, *f; + PyObject *v; CLAMP(begin, 0, self->size); CLAMP(end, 0, self->size); @@ -486,16 +404,15 @@ static int Vector_ass_slice(VectorObject * self, int begin, int end, return EXPP_ReturnIntError(PyExc_RuntimeError, "vector[begin:end] = []: unable to read sequence\n"); } - - f = PyNumber_Float(v); - if(f == NULL) { /* parsed item not a number */ + + if(!PyNumber_Check(v)) { /* parsed item not a number */ Py_DECREF(v); return EXPP_ReturnIntError(PyExc_TypeError, "vector[begin:end] = []: sequence argument not a number\n"); } - vec[i] = (float)PyFloat_AS_DOUBLE(f); - EXPP_decr2(f,v); + vec[i] = (float)PyFloat_AsDouble(v); + Py_DECREF(v); } /*parsed well - now set in vector*/ for(y = 0; y < size; y++){ @@ -508,7 +425,7 @@ static int Vector_ass_slice(VectorObject * self, int begin, int end, addition*/ static PyObject *Vector_add(PyObject * v1, PyObject * v2) { - int x; + int i; float vec[4]; VectorObject *vec1 = NULL, *vec2 = NULL; @@ -526,8 +443,8 @@ static PyObject *Vector_add(PyObject * v1, PyObject * v2) return EXPP_ReturnPyObjError(PyExc_AttributeError, "Vector addition: vectors must have the same dimensions for this operation\n"); - for(x = 0; x < vec1->size; x++) { - vec[x] = vec1->vec[x] + vec2->vec[x]; + for(i = 0; i < vec1->size; i++) { + vec[i] = vec1->vec[i] + vec2->vec[i]; } return newVectorObject(vec, vec1->size, Py_NEW); } @@ -537,8 +454,8 @@ static PyObject *Vector_add(PyObject * v1, PyObject * v2) PointObject *pt = (PointObject*)v2; if(pt->size == vec1->size){ - for(x = 0; x < vec1->size; x++){ - vec[x] = vec1->vec[x] + pt->coord[x]; + for(i = 0; i < vec1->size; i++){ + vec[i] = vec1->vec[i] + pt->coord[i]; } }else{ return EXPP_ReturnPyObjError(PyExc_AttributeError, @@ -550,11 +467,60 @@ static PyObject *Vector_add(PyObject * v1, PyObject * v2) return EXPP_ReturnPyObjError(PyExc_AttributeError, "Vector addition: arguments not valid for this operation....\n"); } + +/* ------------------------obj += obj------------------------------ + addition in place */ +static PyObject *Vector_iadd(PyObject * v1, PyObject * v2) +{ + int i; + + VectorObject *vec1 = NULL, *vec2 = NULL; + + if VectorObject_Check(v1) + vec1= (VectorObject *)v1; + + if VectorObject_Check(v2) + vec2= (VectorObject *)v2; + + /* make sure v1 is always the vector */ + if (vec1 && vec2 ) { + /*VECTOR + VECTOR*/ + if(vec1->size != vec2->size) + return EXPP_ReturnPyObjError(PyExc_AttributeError, + "Vector addition: vectors must have the same dimensions for this operation\n"); + + for(i = 0; i < vec1->size; i++) { + vec1->vec[i] += vec2->vec[i]; + } + Py_INCREF( v1 ); + return v1; + } + + if(PointObject_Check(v2)){ /*VECTOR + POINT*/ + /*Point translation*/ + PointObject *pt = (PointObject*)v2; + + if(pt->size == vec1->size){ + for(i = 0; i < vec1->size; i++){ + vec1->vec[i] += pt->coord[i]; + } + }else{ + return EXPP_ReturnPyObjError(PyExc_AttributeError, + "Vector addition: arguments are the wrong size....\n"); + } + Py_INCREF( v1 ); + return v1; + } + + return EXPP_ReturnPyObjError(PyExc_AttributeError, + "Vector addition: arguments not valid for this operation....\n"); +} + /*------------------------obj - obj------------------------------ subtraction*/ static PyObject *Vector_sub(PyObject * v1, PyObject * v2) { - int x, size; + int i; float vec[4]; VectorObject *vec1 = NULL, *vec2 = NULL; @@ -565,17 +531,44 @@ static PyObject *Vector_sub(PyObject * v1, PyObject * v2) vec1 = (VectorObject*)v1; vec2 = (VectorObject*)v2; + if(vec1->size != vec2->size) + return EXPP_ReturnPyObjError(PyExc_AttributeError, + "Vector subtraction: vectors must have the same dimensions for this operation\n"); + + for(i = 0; i < vec1->size; i++) { + vec[i] = vec1->vec[i] - vec2->vec[i]; + } + + return newVectorObject(vec, vec1->size, Py_NEW); +} + +/*------------------------obj -= obj------------------------------ + subtraction*/ +static PyObject *Vector_isub(PyObject * v1, PyObject * v2) +{ + int i, size; + VectorObject *vec1 = NULL, *vec2 = NULL; + + if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) + return EXPP_ReturnPyObjError(PyExc_AttributeError, + "Vector subtraction: arguments not valid for this operation....\n"); + + vec1 = (VectorObject*)v1; + vec2 = (VectorObject*)v2; + if(vec1->size != vec2->size) return EXPP_ReturnPyObjError(PyExc_AttributeError, "Vector subtraction: vectors must have the same dimensions for this operation\n"); size = vec1->size; - for(x = 0; x < size; x++) { - vec[x] = vec1->vec[x] - vec2->vec[x]; + for(i = 0; i < vec1->size; i++) { + vec1->vec[i] = vec1->vec[i] - vec2->vec[i]; } - return newVectorObject(vec, size, Py_NEW); + Py_INCREF( v1 ); + return v1; } + /*------------------------obj * obj------------------------------ mulplication*/ static PyObject *Vector_mul(PyObject * v1, PyObject * v2) @@ -590,7 +583,7 @@ static PyObject *Vector_mul(PyObject * v1, PyObject * v2) /* make sure v1 is always the vector */ if (vec1 && vec2 ) { - int x; + int i; double dot = 0.0f; if(vec1->size != vec2->size) @@ -598,8 +591,8 @@ static PyObject *Vector_mul(PyObject * v1, PyObject * v2) "Vector multiplication: vectors must have the same dimensions for this operation\n"); /*dot product*/ - for(x = 0; x < vec1->size; x++) { - dot += vec1->vec[x] * vec2->vec[x]; + for(i = 0; i < vec1->size; i++) { + dot += vec1->vec[i] * vec2->vec[i]; } return PyFloat_FromDouble(dot); } @@ -612,12 +605,12 @@ static PyObject *Vector_mul(PyObject * v1, PyObject * v2) if (PyNumber_Check(v2)) { /* VEC * NUM */ - int x; + int i; float vec[4]; float scalar = (float)PyFloat_AsDouble( v2 ); - for(x = 0; x < vec1->size; x++) { - vec[x] = vec1->vec[x] * scalar; + for(i = 0; i < vec1->size; i++) { + vec[i] = vec1->vec[i] * scalar; } return newVectorObject(vec, vec1->size, Py_NEW); @@ -640,11 +633,64 @@ static PyObject *Vector_mul(PyObject * v1, PyObject * v2) "Vector multiplication: arguments not acceptable for this operation\n"); } +/*------------------------obj *= obj------------------------------ + in place mulplication */ +static PyObject *Vector_imul(PyObject * v1, PyObject * v2) +{ + VectorObject *vec = (VectorObject *)v1; + int i; + + /* only support vec*=float and vec*=mat + vec*=vec result is a float so that wont work */ + if (PyNumber_Check(v2)) { + /* VEC * NUM */ + float scalar = (float)PyFloat_AsDouble( v2 ); + + for(i = 0; i < vec->size; i++) { + vec->vec[i] *= scalar; + } + Py_INCREF( v1 ); + return v1; + + } else if (MatrixObject_Check(v2)) { + float vecCopy[4]; + double dot; + int x,y, size= vec->size; + MatrixObject *mat= (MatrixObject*)v2; + + if(mat->colSize != vec->size){ + if(mat->rowSize == 4 && vec->size != 3){ + return EXPP_ReturnPyObjError(PyExc_AttributeError, + "vector * matrix: matrix column size and the vector size must be the same"); + }else{ + vecCopy[3] = 1.0f; + } + } + + for(i = 0; i < size; i++){ + vecCopy[i] = vec->vec[i]; + } + + /*muliplication*/ + for(x = 0, i = 0; x < mat->colSize; x++) { + for(y = 0; y < mat->rowSize; y++) { + dot += mat->matrix[y][x] * vecCopy[y]; + } + vec->vec[i++] = (float)dot; + dot = 0.0f; + } + Py_INCREF( v1 ); + return v1; + } + return EXPP_ReturnPyObjError(PyExc_TypeError, + "Vector multiplication: arguments not acceptable for this operation\n"); +} + /*------------------------obj / obj------------------------------ divide*/ static PyObject *Vector_div(PyObject * v1, PyObject * v2) { - int x, size; + int i, size; float vec[4], scalar; VectorObject *vec1 = NULL; @@ -665,21 +711,52 @@ static PyObject *Vector_div(PyObject * v1, PyObject * v2) "Vector division: divide by zero error.\n"); size = vec1->size; - for(x = 0; x < size; x++) { - vec[x] = vec1->vec[x] / scalar; + for(i = 0; i < size; i++) { + vec[i] = vec1->vec[i] / scalar; } return newVectorObject(vec, size, Py_NEW); } +/*------------------------obj / obj------------------------------ + divide*/ +static PyObject *Vector_idiv(PyObject * v1, PyObject * v2) +{ + int i, size; + float scalar; + VectorObject *vec1 = NULL; + + /*if(!VectorObject_Check(v1)) + return EXPP_ReturnIntError(PyExc_TypeError, + "Vector division: Vector must be divided by a float\n");*/ + + vec1 = (VectorObject*)v1; /* vector */ + + if(!PyNumber_Check(v2)) /* parsed item not a number */ + return EXPP_ReturnPyObjError(PyExc_TypeError, + "Vector division: Vector must be divided by a float\n"); + + scalar = (float)PyFloat_AsDouble(v2); + + if(scalar==0.0) /* not a vector */ + return EXPP_ReturnPyObjError(PyExc_ZeroDivisionError, + "Vector division: divide by zero error.\n"); + + size = vec1->size; + for(i = 0; i < size; i++) { + vec1->vec[i] /= scalar; + } + Py_INCREF( v1 ); + return v1; +} /*-------------------------- -obj ------------------------------- returns the negative of this object*/ static PyObject *Vector_neg(VectorObject *self) { - int x; + int i; float vec[4]; - for(x = 0; x < self->size; x++){ - vec[x] = -self->vec[x]; + for(i = 0; i < self->size; i++){ + vec[i] = -self->vec[i]; } return newVectorObject(vec, self->size, Py_NEW); @@ -705,8 +782,8 @@ static int Vector_coerce(PyObject ** v1, PyObject ** v2) /*------------------------tp_doc*/ static char VectorObject_doc[] = "This is a wrapper for vector objects."; -/*------------------------vec_magnitude (internal)*/ -static double vec_magnitude(float *data, int size) +/*------------------------vec_magnitude_nosqrt (internal) - for comparing only */ +static double vec_magnitude_nosqrt(float *data, int size) { double dot = 0.0f; int i; @@ -714,8 +791,14 @@ static double vec_magnitude(float *data, int size) for(i=0; ivec, vecA->size); - lenB = vec_magnitude(vecB->vec, vecB->size); + lenA = vec_magnitude_nosqrt(vecA->vec, vecA->size); + lenB = vec_magnitude_nosqrt(vecB->vec, vecB->size); if( lenA < lenB ){ result = 1; } break; case Py_LE: - lenA = vec_magnitude(vecA->vec, vecA->size); - lenB = vec_magnitude(vecB->vec, vecB->size); + lenA = vec_magnitude_nosqrt(vecA->vec, vecA->size); + lenB = vec_magnitude_nosqrt(vecB->vec, vecB->size); if( lenA < lenB ){ result = 1; }else{ @@ -772,15 +855,15 @@ PyObject* Vector_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_t } break; case Py_GT: - lenA = vec_magnitude(vecA->vec, vecA->size); - lenB = vec_magnitude(vecB->vec, vecB->size); + lenA = vec_magnitude_nosqrt(vecA->vec, vecA->size); + lenB = vec_magnitude_nosqrt(vecB->vec, vecB->size); if( lenA > lenB ){ result = 1; } break; case Py_GE: - lenA = vec_magnitude(vecA->vec, vecA->size); - lenB = vec_magnitude(vecB->vec, vecB->size); + lenA = vec_magnitude_nosqrt(vecA->vec, vecA->size); + lenB = vec_magnitude_nosqrt(vecB->vec, vecB->size); if( lenA > lenB ){ result = 1; }else{ @@ -822,48 +905,224 @@ static PyNumberMethods Vector_NumMethods = { (binaryfunc) Vector_sub, /* __sub__ */ (binaryfunc) Vector_mul, /* __mul__ */ (binaryfunc) Vector_div, /* __div__ */ - (binaryfunc) 0, /* __mod__ */ - (binaryfunc) 0, /* __divmod__ */ - (ternaryfunc) 0, /* __pow__ */ + (binaryfunc) NULL, /* __mod__ */ + (binaryfunc) NULL, /* __divmod__ */ + (ternaryfunc) NULL, /* __pow__ */ (unaryfunc) Vector_neg, /* __neg__ */ - (unaryfunc) 0, /* __pos__ */ - (unaryfunc) 0, /* __abs__ */ - (inquiry) 0, /* __nonzero__ */ - (unaryfunc) 0, /* __invert__ */ - (binaryfunc) 0, /* __lshift__ */ - (binaryfunc) 0, /* __rshift__ */ - (binaryfunc) 0, /* __and__ */ - (binaryfunc) 0, /* __xor__ */ - (binaryfunc) 0, /* __or__ */ + (unaryfunc) NULL, /* __pos__ */ + (unaryfunc) NULL, /* __abs__ */ + (inquiry) NULL, /* __nonzero__ */ + (unaryfunc) NULL, /* __invert__ */ + (binaryfunc) NULL, /* __lshift__ */ + (binaryfunc) NULL, /* __rshift__ */ + (binaryfunc) NULL, /* __and__ */ + (binaryfunc) NULL, /* __xor__ */ + (binaryfunc) NULL, /* __or__ */ (coercion) Vector_coerce, /* __coerce__ */ - (unaryfunc) 0, /* __int__ */ - (unaryfunc) 0, /* __long__ */ - (unaryfunc) 0, /* __float__ */ - (unaryfunc) 0, /* __oct__ */ - (unaryfunc) 0, /* __hex__ */ - - //~ /* Added in release 2.0 */ - //~ binaryfunc nb_inplace_add; - //~ binaryfunc nb_inplace_subtract; - //~ binaryfunc nb_inplace_multiply; - //~ binaryfunc nb_inplace_divide; - //~ binaryfunc nb_inplace_remainder; - //~ ternaryfunc nb_inplace_power; - //~ binaryfunc nb_inplace_lshift; - //~ binaryfunc nb_inplace_rshift; - //~ binaryfunc nb_inplace_and; - //~ binaryfunc nb_inplace_xor; - //~ binaryfunc nb_inplace_or; + (unaryfunc) NULL, /* __int__ */ + (unaryfunc) NULL, /* __long__ */ + (unaryfunc) NULL, /* __float__ */ + (unaryfunc) NULL, /* __oct__ */ + (unaryfunc) NULL, /* __hex__ */ + + /* Added in release 2.0 */ + (binaryfunc) Vector_iadd, /*__iadd__*/ + (binaryfunc) Vector_isub, /*__isub__*/ + (binaryfunc) Vector_imul, /*__imul__*/ + (binaryfunc) Vector_idiv, /*__idiv__*/ + (binaryfunc) NULL, /*__imod__*/ + (ternaryfunc) NULL, /*__ipow__*/ + (binaryfunc) NULL, /*__ilshift__*/ + (binaryfunc) NULL, /*__irshift__*/ + (binaryfunc) NULL, /*__iand__*/ + (binaryfunc) NULL, /*__ixor__*/ + (binaryfunc) NULL, /*__ior__*/ - //~ /* Added in release 2.2 */ - //~ /* The following require the Py_TPFLAGS_HAVE_CLASS flag */ - //~ binaryfunc nb_floor_divide; - //~ binaryfunc nb_true_divide; - //~ binaryfunc nb_inplace_floor_divide; - //~ binaryfunc nb_inplace_true_divide; + /* Added in release 2.2 */ + /* The following require the Py_TPFLAGS_HAVE_CLASS flag */ + (binaryfunc) NULL, /*__floordiv__ __rfloordiv__*/ + (binaryfunc) NULL, /*__truediv__ __rfloordiv__*/ + (binaryfunc) NULL, /*__ifloordiv__*/ + (binaryfunc) NULL, /*__itruediv__*/ }; /*------------------PY_OBECT DEFINITION--------------------------*/ +/* + * vector axis, vector.x/y/z/w + */ + +static PyObject *Vector_getAxis( VectorObject * self, void *type ) +{ + switch( (long)type ) { + case 'X': /* these are backwards, but that how it works */ + return PyFloat_FromDouble(self->vec[0]); + case 'Y': + return PyFloat_FromDouble(self->vec[1]); + case 'Z': /* these are backwards, but that how it works */ + if(self->size < 3) + return EXPP_ReturnPyObjError(PyExc_AttributeError, + "vector.z: error, cannot get this axis for a 2D vector\n"); + else + return PyFloat_FromDouble(self->vec[2]); + case 'W': + if(self->size < 4) + return EXPP_ReturnPyObjError(PyExc_AttributeError, + "vector.w: error, cannot get this axis for a 3D vector\n"); + + return PyFloat_FromDouble(self->vec[4]); + default: + { + char errstr[1024]; + sprintf( errstr, "undefined type '%d' in Vector_getAxis", + (int)((long)type & 0xff)); + return EXPP_ReturnPyObjError( PyExc_RuntimeError, errstr ); + } + } +} + +static int Vector_setAxis( VectorObject * self, PyObject * value, void * type ) +{ + float param; + + if (!PyNumber_Check(value)) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected a number for the vector axis" ); + + param= (float)PyFloat_AsDouble( value ); + + switch( (long)type ) { + case 'X': /* these are backwards, but that how it works */ + self->vec[0]= param; + break; + case 'Y': + self->vec[1]= param; + break; + case 'Z': /* these are backwards, but that how it works */ + if(self->size < 3) + return EXPP_ReturnIntError(PyExc_AttributeError, + "vector.z: error, cannot get this axis for a 2D vector\n"); + self->vec[2]= param; + break; + case 'W': + if(self->size < 4) + return EXPP_ReturnIntError(PyExc_AttributeError, + "vector.w: error, cannot get this axis for a 3D vector\n"); + + self->vec[3]= param; + break; + default: + { + char errstr[1024]; + sprintf( errstr, "undefined type '%d' in Vector_setAxis", + (int)((long)type & 0xff)); + return EXPP_ReturnIntError( PyExc_RuntimeError, errstr ); + } + } + + return 0; +} + +/* vector.length */ +static PyObject *Vector_getLength( VectorObject * self, void *type ) +{ + double dot = 0.0f; + int i; + + for(i = 0; i < self->size; i++){ + dot += (self->vec[i] * self->vec[i]); + } + return PyFloat_FromDouble(sqrt(dot)); +} + +static int Vector_setLength( VectorObject * self, PyObject * value ) +{ + double dot = 0.0f, param; + int i; + + if (!PyNumber_Check(value)) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected a number for the vector axis" ); + + param= PyFloat_AsDouble( value ); + + if (param < 0) + return EXPP_ReturnIntError( PyExc_TypeError, + "cannot set a vectors length to a negative value" ); + + if (param==0) { + for(i = 0; i < self->size; i++){ + self->vec[i]= 0; + } + return 0; + } + + for(i = 0; i < self->size; i++){ + dot += (self->vec[i] * self->vec[i]); + } + + if (!dot) /* cant sqrt zero */ + return 0; + + dot = sqrt(dot); + + if (dot==param) + return 0; + + dot= dot/param; + + for(i = 0; i < self->size; i++){ + self->vec[i]= self->vec[i] / dot; + } + + return 0; +} + +static PyObject *Vector_getWrapped( VectorObject * self, void *type ) +{ + if (self->wrapped == Py_WRAP) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; +} + + +/*****************************************************************************/ +/* Python attributes get/set structure: */ +/*****************************************************************************/ +static PyGetSetDef Vector_getseters[] = { + {"x", + (getter)Vector_getAxis, (setter)Vector_setAxis, + "Vector X axis", + (void *)'X'}, + {"y", + (getter)Vector_getAxis, (setter)Vector_setAxis, + "Vector Y axis", + (void *)'Y'}, + {"z", + (getter)Vector_getAxis, (setter)Vector_setAxis, + "Vector Z axis", + (void *)'Z'}, + {"w", + (getter)Vector_getAxis, (setter)Vector_setAxis, + "Vector Z axis", + (void *)'W'}, + {"length", + (getter)Vector_getLength, (setter)Vector_setLength, + "Vector Length", + NULL}, + {"magnitude", + (getter)Vector_getLength, (setter)Vector_setLength, + "Vector Length", + NULL}, + {"wrapped", + (getter)Vector_getWrapped, (setter)NULL, + "Vector Length", + NULL}, + {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ +}; + + + /* Note Py_TPFLAGS_CHECKTYPES allows us to avoid casting all types to Vector when coercing but this means for eg that @@ -871,55 +1130,88 @@ static PyNumberMethods Vector_NumMethods = { */ PyTypeObject vector_Type = { - PyObject_HEAD_INIT(NULL) /*tp_head*/ - 0, /*tp_internal*/ - "vector", /*tp_name*/ - sizeof(VectorObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)Vector_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - (getattrfunc)Vector_getattr, /*tp_getattr*/ - (setattrfunc) Vector_setattr, /*tp_setattr*/ - 0, /*tp_compare*/ - (reprfunc) Vector_repr, /*tp_repr*/ - &Vector_NumMethods, /*tp_as_number*/ - &Vector_SeqMethods, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ - VectorObject_doc, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - (richcmpfunc)Vector_richcmpr, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - 0, /*tp_methods*/ - 0, /*tp_members*/ - 0, /*tp_getset*/ - 0, /*tp_base*/ - 0, /*tp_dict*/ - 0, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ - 0, /*tp_init*/ - 0, /*tp_alloc*/ - 0, /*tp_new*/ - 0, /*tp_free*/ - 0, /*tp_is_gc*/ - 0, /*tp_bases*/ - 0, /*tp_mro*/ - 0, /*tp_cache*/ - 0, /*tp_subclasses*/ - 0, /*tp_weaklist*/ - 0 /*tp_del*/ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ + /* For printing, in format "." */ + "Blender Vector", /* char *tp_name; */ + sizeof( VectorObject ), /* int tp_basicsize; */ + 0, /* tp_itemsize; For allocation */ + + /* Methods to implement standard operations */ + + ( destructor ) Vector_dealloc,/* destructor tp_dealloc; */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, /* cmpfunc tp_compare; */ + ( reprfunc ) Vector_repr, /* reprfunc tp_repr; */ + + /* Method suites for standard classes */ + + &Vector_NumMethods, /* PyNumberMethods *tp_as_number; */ + &Vector_SeqMethods, /* PySequenceMethods *tp_as_sequence; */ + NULL, /* PyMappingMethods *tp_as_mapping; */ + + /* More standard operations (here for binary compatibility) */ + + NULL, /* hashfunc tp_hash; */ + NULL, /* ternaryfunc tp_call; */ + NULL, /* reprfunc tp_str; */ + NULL, /* getattrofunc tp_getattro; */ + NULL, /* setattrofunc tp_setattro; */ + + /* Functions to access object as input/output buffer */ + NULL, /* PyBufferProcs *tp_as_buffer; */ + + /*** Flags to define presence of optional/expanded features ***/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* long tp_flags; */ + + VectorObject_doc, /* char *tp_doc; Documentation string */ + /*** Assigned meaning in release 2.0 ***/ + /* call function for all accessible objects */ + NULL, /* traverseproc tp_traverse; */ + + /* delete references to contained objects */ + NULL, /* inquiry tp_clear; */ + + /*** Assigned meaning in release 2.1 ***/ + /*** rich comparisons ***/ + (richcmpfunc)Vector_richcmpr, /* richcmpfunc tp_richcompare; */ + + /*** weak reference enabler ***/ + 0, /* long tp_weaklistoffset; */ + + /*** Added in release 2.2 ***/ + /* Iterators */ + NULL, /* getiterfunc tp_iter; */ + NULL, /* iternextfunc tp_iternext; */ + + /*** Attribute descriptor and subclassing stuff ***/ + Vector_methods, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + Vector_getseters, /* struct PyGetSetDef *tp_getset; */ + NULL, /* struct _typeobject *tp_base; */ + NULL, /* PyObject *tp_dict; */ + NULL, /* descrgetfunc tp_descr_get; */ + NULL, /* descrsetfunc tp_descr_set; */ + 0, /* long tp_dictoffset; */ + NULL, /* initproc tp_init; */ + NULL, /* allocfunc tp_alloc; */ + NULL, /* newfunc tp_new; */ + /* Low-level free-memory routine */ + NULL, /* freefunc tp_free; */ + /* For PyObject_IS_GC */ + NULL, /* inquiry tp_is_gc; */ + NULL, /* PyObject *tp_bases; */ + /* method resolution order */ + NULL, /* PyObject *tp_mro; */ + NULL, /* PyObject *tp_cache; */ + NULL, /* PyObject *tp_subclasses; */ + NULL, /* PyObject *tp_weaklist; */ + NULL }; + /*------------------------newVectorObject (internal)------------- creates a new vector object pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER @@ -928,11 +1220,9 @@ PyTypeObject vector_Type = { (i.e. it must be created here with PyMEM_malloc())*/ PyObject *newVectorObject(float *vec, int size, int type) { - VectorObject *self; - int x; - - vector_Type.ob_type = &PyType_Type; - self = PyObject_NEW(VectorObject, &vector_Type); + int i; + VectorObject *self = PyObject_NEW(VectorObject, &vector_Type); + self->data.blend_data = NULL; self->data.py_data = NULL; if(size > 4 || size < 2) @@ -947,14 +1237,14 @@ PyObject *newVectorObject(float *vec, int size, int type) self->data.py_data = PyMem_Malloc(size * sizeof(float)); self->vec = self->data.py_data; if(!vec) { /*new empty*/ - for(x = 0; x < size; x++){ - self->vec[x] = 0.0f; + for(i = 0; i < size; i++){ + self->vec[i] = 0.0f; } if(size == 4) /* do the homogenous thing */ self->vec[3] = 1.0f; }else{ - for(x = 0; x < size; x++){ - self->vec[x] = vec[x]; + for(i = 0; i < size; i++){ + self->vec[i] = vec[i]; } } self->wrapped = Py_NEW; @@ -971,9 +1261,9 @@ PyObject *newVectorObject(float *vec, int size, int type) set the vector to it's negative -x, -y, -z */ PyObject *Vector_Negate(VectorObject * self) { - int x; - for(x = 0; x < self->size; x++) { - self->vec[x] = -(self->vec[x]); + int i; + for(i = 0; i < self->size; i++) { + self->vec[i] = -(self->vec[i]); } /*printf("Vector.negate(): Deprecated: use -vector instead\n");*/ return EXPP_incr_ret((PyObject*)self); -- cgit v1.2.3