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