Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 * 00023 * Contributor(s): none yet. 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00033 #ifndef __KX_PYMATH_H__ 00034 #define __KX_PYMATH_H__ 00035 00036 #include "MT_Point2.h" 00037 #include "MT_Point3.h" 00038 #include "MT_Vector2.h" 00039 #include "MT_Vector3.h" 00040 #include "MT_Vector4.h" 00041 #include "MT_Matrix3x3.h" 00042 #include "MT_Matrix4x4.h" 00043 00044 #include "KX_Python.h" 00045 #include "PyObjectPlus.h" 00046 00047 #ifdef WITH_PYTHON 00048 #ifdef USE_MATHUTILS 00049 extern "C" { 00050 #include "../../blender/python/mathutils/mathutils.h" /* so we can have mathutils callbacks */ 00051 } 00052 #endif 00053 00054 inline unsigned int Size(const MT_Matrix4x4&) { return 4; } 00055 inline unsigned int Size(const MT_Matrix3x3&) { return 3; } 00056 inline unsigned int Size(const MT_Tuple2&) { return 2; } 00057 inline unsigned int Size(const MT_Tuple3&) { return 3; } 00058 inline unsigned int Size(const MT_Tuple4&) { return 4; } 00059 00063 template<class T> 00064 bool PyMatTo(PyObject* pymat, T& mat) 00065 { 00066 bool noerror = true; 00067 mat.setIdentity(); 00068 00069 00070 #ifdef USE_MATHUTILS 00071 00072 if (MatrixObject_Check(pymat)) 00073 { 00074 MatrixObject *pymatrix = (MatrixObject *)pymat; 00075 00076 if (BaseMath_ReadCallback(pymatrix) == -1) 00077 return false; 00078 00079 if (pymatrix->num_col != Size(mat) || pymatrix->num_row != Size(mat)) 00080 return false; 00081 00082 for (unsigned int row = 0; row < Size(mat); row++) 00083 { 00084 for (unsigned int col = 0; col < Size(mat); col++) 00085 { 00086 mat[row][col] = *(pymatrix->matrix + col * pymatrix->num_row + row); 00087 } 00088 } 00089 } 00090 else 00091 00092 #endif /* USE_MATHUTILS */ 00093 00094 00095 if (PySequence_Check(pymat)) 00096 { 00097 unsigned int rows = PySequence_Size(pymat); 00098 if (rows != Size(mat)) 00099 return false; 00100 00101 for (unsigned int row = 0; noerror && row < rows; row++) 00102 { 00103 PyObject *pyrow = PySequence_GetItem(pymat, row); /* new ref */ 00104 if (!PyErr_Occurred() && PySequence_Check(pyrow)) 00105 { 00106 unsigned int cols = PySequence_Size(pyrow); 00107 if (cols != Size(mat)) 00108 noerror = false; 00109 else 00110 { 00111 for( unsigned int col = 0; col < cols; col++) 00112 { 00113 PyObject *item = PySequence_GetItem(pyrow, col); /* new ref */ 00114 mat[row][col] = PyFloat_AsDouble(item); 00115 Py_DECREF(item); 00116 } 00117 } 00118 } else 00119 noerror = false; 00120 Py_DECREF(pyrow); 00121 } 00122 } else 00123 noerror = false; 00124 00125 if (noerror==false) 00126 PyErr_SetString(PyExc_TypeError, "could not be converted to a matrix (sequence of sequences)"); 00127 00128 return noerror; 00129 } 00130 00134 template<class T> 00135 bool PyVecTo(PyObject* pyval, T& vec) 00136 { 00137 #ifdef USE_MATHUTILS 00138 /* no need for BaseMath_ReadCallback() here, reading the sequences will do this */ 00139 00140 if(VectorObject_Check(pyval)) { 00141 VectorObject *pyvec= (VectorObject *)pyval; 00142 if(BaseMath_ReadCallback(pyvec) == -1) { 00143 return false; /* exception raised */ 00144 } 00145 if (pyvec->size != Size(vec)) { 00146 PyErr_Format(PyExc_AttributeError, "error setting vector, %d args, should be %d", pyvec->size, Size(vec)); 00147 return false; 00148 } 00149 vec.setValue((float *) pyvec->vec); 00150 return true; 00151 } 00152 else if(QuaternionObject_Check(pyval)) { 00153 QuaternionObject *pyquat= (QuaternionObject *)pyval; 00154 if(BaseMath_ReadCallback(pyquat) == -1) { 00155 return false; /* exception raised */ 00156 } 00157 if (4 != Size(vec)) { 00158 PyErr_Format(PyExc_AttributeError, "error setting vector, %d args, should be %d", 4, Size(vec)); 00159 return false; 00160 } 00161 /* xyzw -> wxyz reordering is done by PyQuatTo */ 00162 vec.setValue((float *) pyquat->quat); 00163 return true; 00164 } 00165 else if(EulerObject_Check(pyval)) { 00166 EulerObject *pyeul= (EulerObject *)pyval; 00167 if(BaseMath_ReadCallback(pyeul) == -1) { 00168 return false; /* exception raised */ 00169 } 00170 if (3 != Size(vec)) { 00171 PyErr_Format(PyExc_AttributeError, "error setting vector, %d args, should be %d", 3, Size(vec)); 00172 return false; 00173 } 00174 vec.setValue((float *) pyeul->eul); 00175 return true; 00176 } else 00177 #endif 00178 if(PyTuple_Check(pyval)) 00179 { 00180 unsigned int numitems = PyTuple_GET_SIZE(pyval); 00181 if (numitems != Size(vec)) { 00182 PyErr_Format(PyExc_AttributeError, "error setting vector, %d args, should be %d", numitems, Size(vec)); 00183 return false; 00184 } 00185 00186 for (unsigned int x = 0; x < numitems; x++) 00187 vec[x] = PyFloat_AsDouble(PyTuple_GET_ITEM(pyval, x)); /* borrow ref */ 00188 00189 if (PyErr_Occurred()) { 00190 PyErr_SetString(PyExc_AttributeError, "one or more of the items in the sequence was not a float"); 00191 return false; 00192 } 00193 00194 return true; 00195 } 00196 else if (PyObject_TypeCheck(pyval, (PyTypeObject *)&PyObjectPlus::Type)) 00197 { /* note, include this check because PySequence_Check does too much introspection 00198 * on the PyObject (like getting its __class__, on a BGE type this means searching up 00199 * the parent list each time only to discover its not a sequence. 00200 * GameObjects are often used as an alternative to vectors so this is a common case 00201 * better to do a quick check for it, likely the error below will be ignored. 00202 * 00203 * This is not 'correct' since we have proxy type CListValues's which could 00204 * contain floats/ints but there no cases of CValueLists being this way 00205 */ 00206 PyErr_Format(PyExc_AttributeError, "expected a sequence type"); 00207 return false; 00208 } 00209 else if (PySequence_Check(pyval)) 00210 { 00211 unsigned int numitems = PySequence_Size(pyval); 00212 if (numitems != Size(vec)) { 00213 PyErr_Format(PyExc_AttributeError, "error setting vector, %d args, should be %d", numitems, Size(vec)); 00214 return false; 00215 } 00216 00217 for (unsigned int x = 0; x < numitems; x++) 00218 { 00219 PyObject *item = PySequence_GetItem(pyval, x); /* new ref */ 00220 vec[x] = PyFloat_AsDouble(item); 00221 Py_DECREF(item); 00222 } 00223 00224 if (PyErr_Occurred()) { 00225 PyErr_SetString(PyExc_AttributeError, "one or more of the items in the sequence was not a float"); 00226 return false; 00227 } 00228 00229 return true; 00230 } else 00231 { 00232 PyErr_Format(PyExc_AttributeError, "not a sequence type, expected a sequence of numbers size %d", Size(vec)); 00233 } 00234 00235 return false; 00236 } 00237 00238 00239 bool PyQuatTo(PyObject* pyval, MT_Quaternion &qrot); 00240 00241 bool PyOrientationTo(PyObject* pyval, MT_Matrix3x3 &mat, const char *error_prefix); 00242 00246 PyObject* PyObjectFrom(const MT_Matrix4x4 &mat); 00247 00251 PyObject* PyObjectFrom(const MT_Matrix3x3 &mat); 00252 00256 PyObject* PyObjectFrom(const MT_Tuple2 &vec); 00257 00261 PyObject* PyObjectFrom(const MT_Tuple3 &vec); 00262 00263 #ifdef USE_MATHUTILS 00264 00267 PyObject* PyObjectFrom(const MT_Quaternion &qrot); 00268 #endif 00269 00273 PyObject* PyObjectFrom(const MT_Tuple4 &pos); 00274 00275 #endif 00276 00277 #endif // WITH_PYTHON