mathutils matrix initialization now matches other mathutils types.
authorCampbell Barton <ideasman42@gmail.com>
Sun, 9 Jan 2011 14:30:16 +0000 (14:30 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Sun, 9 Jan 2011 14:30:16 +0000 (14:30 +0000)
(should have made this change along with the others).
Matrix([1, 2],  [3, 4]) --> Matrix(([1, 2], [3, 4]))
This is so adding initialization args works right.

Also simplify initialization code (re-use slice assignment).

source/blender/python/generic/mathutils_matrix.c
source/blender/python/generic/mathutils_matrix.h

index 35d58ceb255cb63d2b4f74ea303798282aa4bac1..4e33c312bf849bb29c8f8ddd1e128344bbdac560 100644 (file)
@@ -31,7 +31,7 @@
 #include "BLI_blenlib.h"
 #include "BLI_utildefines.h"
 
-
+static int Matrix_ass_slice(MatrixObject * self, int begin, int end, PyObject *value);
 
 /* matrix vector callbacks */
 int mathutils_matrix_vector_cb_index= -1;
@@ -109,80 +109,42 @@ Mathutils_Callback mathutils_matrix_vector_cb = {
 //create a new matrix type
 static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
-       PyObject *argObject, *m, *s;
-       MatrixObject *mat;
-       int argSize, seqSize = 0, i, j;
-       float matrix[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
-               0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
-       float scalar;
-
        if(kwds && PyDict_Size(kwds)) {
                PyErr_SetString(PyExc_TypeError, "mathutils.Matrix(): takes no keyword args");
                return NULL;
        }
 
-       argSize = PyTuple_GET_SIZE(args);
-       if(argSize > MATRIX_MAX_DIM) {  //bad arg nums
-               PyErr_SetString(PyExc_AttributeError, "mathutils.Matrix(): expects 0-4 numeric sequences of the same size");
-               return NULL;
-       } else if (argSize == 0) { //return empty 4D matrix
-               return (PyObject *) newMatrixObject(NULL, 4, 4, Py_NEW, type);
-       }else if (argSize == 1){
-               //copy constructor for matrix objects
-               argObject = PyTuple_GET_ITEM(args, 0);
-               if(MatrixObject_Check(argObject)){
-                       mat = (MatrixObject*)argObject;
-                       if(!BaseMath_ReadCallback(mat))
-                               return NULL;
+       switch(PyTuple_GET_SIZE(args)) {
+               case 0:
+                       return (PyObject *) newMatrixObject(NULL, 4, 4, Py_NEW, type);
+               case 1:
+               {
+                       PyObject *arg= PyTuple_GET_ITEM(args, 0);
 
-                       memcpy(matrix, mat->contigPtr, sizeof(float) * mat->rowSize * mat->colSize);
-                       argSize = mat->rowSize;
-                       seqSize = mat->colSize;
-               }
-       }else{ //2-4 arguments (all seqs? all same size?)
-               for(i =0; i < argSize; i++){
-                       argObject = PyTuple_GET_ITEM(args, i);
-                       if (PySequence_Check(argObject)) { //seq?
-                               if(seqSize){ //0 at first
-                                       if(PySequence_Length(argObject) != seqSize){ //seq size not same
-                                               PyErr_SetString(PyExc_AttributeError, "mathutils.Matrix(): expects 0-4 numeric sequences of the same size");
-                                               return NULL;
-                                       }
-                               }
-                               seqSize = PySequence_Length(argObject);
-                       }else{ //arg not a sequence
-                               PyErr_SetString(PyExc_TypeError, "mathutils.Matrix(): expects 0-4 numeric sequences of the same size");
-                               return NULL;
-                       }
-               }
-               //all is well... let's continue parsing
-               for (i = 0; i < argSize; i++){
-                       m = PyTuple_GET_ITEM(args, i);
-                       if (m == NULL) { // Failed to read sequence
-                               PyErr_SetString(PyExc_RuntimeError, "mathutils.Matrix(): failed to parse arguments");
-                               return NULL;
-                       }
+                       const unsigned short row_size= PySequence_Size(arg); /* -1 is an error, size checks will accunt for this */
 
-                       for (j = 0; j < seqSize; j++) {
-                               s = PySequence_GetItem(m, j);
-                               if (s == NULL) { // Failed to read sequence
-                                       PyErr_SetString(PyExc_RuntimeError, "mathutils.Matrix(): failed to parse arguments");
-                                       return NULL;
-                               }
-                               
-                               scalar= (float)PyFloat_AsDouble(s);
-                               Py_DECREF(s);
-                               
-                               if(scalar==-1 && PyErr_Occurred()) { // parsed item is not a number
-                                       PyErr_SetString(PyExc_AttributeError, "mathutils.Matrix(): expects 0-4 numeric sequences of the same size");
-                                       return NULL;
-                               }
+                       if(IN_RANGE_INCL(row_size, 2, 4)) {
+                               PyObject *item= PySequence_GetItem(arg, 0);
+                               const unsigned short col_size= PySequence_Size(item);
+                               Py_XDECREF(item);
 
-                               matrix[(seqSize*i)+j]= scalar;
+                               if(IN_RANGE_INCL(col_size, 2, 4)) {
+                                       /* sane row & col size, new matrix and assign as slice  */
+                                       PyObject *matrix= newMatrixObject(NULL, row_size, col_size, Py_NEW, type);
+                                       if(Matrix_ass_slice((MatrixObject *)matrix, 0, INT_MAX, arg) == 0) {
+                                               return matrix;
+                                       }
+                                       else { /* matrix ok, slice assignment not */
+                                               Py_DECREF(matrix);
+                                       }
+                               }
                        }
                }
        }
-       return newMatrixObject(matrix, argSize, seqSize, Py_NEW, type);
+
+       /* will overwrite error */
+       PyErr_SetString(PyExc_TypeError, "mathutils.Matrix(): expects no args or 2-4 numeric sequences");
+       return NULL;
 }
 
 /*-----------------------CLASS-METHODS----------------------------*/
@@ -1847,7 +1809,7 @@ self->matrix[1][1] = self->contigPtr[4] */
  (i.e. it was allocated elsewhere by MEM_mallocN())
   pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
  (i.e. it must be created here with PyMEM_malloc())*/
-PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type, PyTypeObject *base_type)
+PyObject *newMatrixObject(float *mat, const unsigned short rowSize, const unsigned short colSize, int type, PyTypeObject *base_type)
 {
        MatrixObject *self;
        int x, row, col;
index f1cce3a45a8289ec63a1704c857136afcc736eed..863cfeb5e05265e3e284cefbb4dcbbe48a1a74b2 100644 (file)
@@ -49,7 +49,7 @@ be stored in py_data) or be a wrapper for data allocated through
 blender (stored in blend_data). This is an either/or struct not both*/
 
 /*prototypes*/
-PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type, PyTypeObject *base_type);
+PyObject *newMatrixObject(float *mat, const unsigned short rowSize, const unsigned short colSize, int type, PyTypeObject *base_type);
 PyObject *newMatrixObject_cb(PyObject *user, int rowSize, int colSize, int cb_type, int cb_subtype);
 
 extern int mathutils_matrix_vector_cb_index;