NLA SoC: Merge from 2.5 - 21179 to 21209
[blender.git] / source / gameengine / Ketsji / KX_MeshProxy.cpp
1 /**
2  * $Id$
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): none yet.
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #ifdef HAVE_CONFIG_H
30 #include <config.h>
31 #endif
32
33 #include "KX_MeshProxy.h"
34 #include "RAS_IPolygonMaterial.h"
35 #include "RAS_MeshObject.h"
36
37 #include "KX_VertexProxy.h"
38 #include "KX_PolyProxy.h"
39
40 #include "KX_PolygonMaterial.h"
41 #include "KX_BlenderMaterial.h"
42
43 #include "KX_PyMath.h"
44 #include "KX_ConvertPhysicsObject.h"
45
46 #include "PyObjectPlus.h" 
47
48 PyTypeObject KX_MeshProxy::Type = {
49 #if (PY_VERSION_HEX >= 0x02060000)
50         PyVarObject_HEAD_INIT(NULL, 0)
51 #else
52         /* python 2.5 and below */
53         PyObject_HEAD_INIT( NULL )  /* required py macro */
54         0,                          /* ob_size */
55 #endif
56         "KX_MeshProxy",
57         sizeof(PyObjectPlus_Proxy),
58         0,
59         py_base_dealloc,
60         0,
61         0,
62         0,
63         0,
64         py_base_repr,
65         0,0,0,0,0,0,
66         py_base_getattro,
67         py_base_setattro,
68         0,0,0,0,0,0,0,0,0,
69         Methods
70 };
71
72 PyParentObject KX_MeshProxy::Parents[] = {
73         &KX_MeshProxy::Type,
74         &CValue::Type,
75         &PyObjectPlus::Type,
76         NULL
77 };
78
79 PyMethodDef KX_MeshProxy::Methods[] = {
80 // Deprecated ----->
81 {"getNumMaterials", (PyCFunction)KX_MeshProxy::sPyGetNumMaterials,METH_VARARGS},
82 {"getNumPolygons", (PyCFunction)KX_MeshProxy::sPyGetNumPolygons,METH_NOARGS},
83 // <-----
84
85 {"getMaterialName", (PyCFunction)KX_MeshProxy::sPyGetMaterialName,METH_VARARGS},
86 {"getTextureName", (PyCFunction)KX_MeshProxy::sPyGetTextureName,METH_VARARGS},
87 {"getVertexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetVertexArrayLength,METH_VARARGS},
88 {"getVertex", (PyCFunction)KX_MeshProxy::sPyGetVertex,METH_VARARGS},
89 {"getPolygon", (PyCFunction)KX_MeshProxy::sPyGetPolygon,METH_VARARGS},
90 KX_PYMETHODTABLE(KX_MeshProxy, reinstancePhysicsMesh),
91 //{"getIndexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetIndexArrayLength,METH_VARARGS},
92
93   {NULL,NULL} //Sentinel
94 };
95
96 PyAttributeDef KX_MeshProxy::Attributes[] = {
97         KX_PYATTRIBUTE_RO_FUNCTION("materials",         KX_MeshProxy, pyattr_get_materials),
98         KX_PYATTRIBUTE_RO_FUNCTION("numPolygons",       KX_MeshProxy, pyattr_get_numPolygons),
99         KX_PYATTRIBUTE_RO_FUNCTION("numMaterials",      KX_MeshProxy, pyattr_get_numMaterials),
100
101         { NULL }        //Sentinel
102 };
103
104 void KX_MeshProxy::SetMeshModified(bool v)
105 {
106         m_meshobj->SetMeshModified(v);
107 }
108
109
110 PyObject* KX_MeshProxy::py_getattro(PyObject *attr)
111 {
112         py_getattro_up(CValue);
113 }
114
115 PyObject* KX_MeshProxy::py_getattro_dict() {
116         py_getattro_dict_up(CValue);
117 }
118
119 int KX_MeshProxy::py_setattro(PyObject *attr, PyObject* value)
120 {
121         py_setattro_up(CValue);
122 }
123
124
125 KX_MeshProxy::KX_MeshProxy(RAS_MeshObject* mesh)
126         : CValue(&Type), m_meshobj(mesh)
127 {
128 }
129
130 KX_MeshProxy::~KX_MeshProxy()
131 {
132 }
133
134
135
136 // stuff for cvalue related things
137 CValue*         KX_MeshProxy::Calc(VALUE_OPERATOR op, CValue *val) { return NULL;}
138 CValue*         KX_MeshProxy::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val) { return NULL;}  
139
140 const STR_String &      KX_MeshProxy::GetText() {return m_meshobj->GetName();};
141 double          KX_MeshProxy::GetNumber() { return -1;}
142 STR_String&     KX_MeshProxy::GetName() { return m_meshobj->GetName();}
143 void            KX_MeshProxy::SetName(const char *name) { };
144 CValue*         KX_MeshProxy::GetReplica() { return NULL;}
145
146
147 // stuff for python integration
148         
149 PyObject* KX_MeshProxy::PyGetNumMaterials(PyObject* args, PyObject* kwds)
150 {
151         int num = m_meshobj->NumMaterials();
152         ShowDeprecationWarning("getNumMaterials()", "the numMaterials property");
153         return PyInt_FromLong(num);
154 }
155
156 PyObject* KX_MeshProxy::PyGetNumPolygons()
157 {
158         int num = m_meshobj->NumPolygons();
159         ShowDeprecationWarning("getNumPolygons()", "the numPolygons property");
160         return PyInt_FromLong(num);
161 }
162
163 PyObject* KX_MeshProxy::PyGetMaterialName(PyObject* args, PyObject* kwds)
164 {
165     int matid= 1;
166         STR_String matname;
167
168         if (PyArg_ParseTuple(args,"i:getMaterialName",&matid))
169         {
170                 matname = m_meshobj->GetMaterialName(matid);
171         }
172         else {
173                 return NULL;
174         }
175
176         return PyString_FromString(matname.Ptr());
177                 
178 }
179         
180
181 PyObject* KX_MeshProxy::PyGetTextureName(PyObject* args, PyObject* kwds)
182 {
183     int matid= 1;
184         STR_String matname;
185
186         if (PyArg_ParseTuple(args,"i:getTextureName",&matid))
187         {
188                 matname = m_meshobj->GetTextureName(matid);
189         }
190         else {
191                 return NULL;
192         }
193
194         return PyString_FromString(matname.Ptr());
195                 
196 }
197
198 PyObject* KX_MeshProxy::PyGetVertexArrayLength(PyObject* args, PyObject* kwds)
199 {
200     int matid= 0;
201         int length = 0;
202
203         
204         if (!PyArg_ParseTuple(args,"i:getVertexArrayLength",&matid))
205                 return NULL;
206         
207
208         RAS_MeshMaterial *mmat = m_meshobj->GetMeshMaterial(matid); /* can be NULL*/
209         
210         if (mmat)
211         {
212                 RAS_IPolyMaterial* mat = mmat->m_bucket->GetPolyMaterial();
213                 if (mat)
214                         length = m_meshobj->NumVertices(mat);
215         }
216         
217         return PyInt_FromLong(length);
218 }
219
220
221 PyObject* KX_MeshProxy::PyGetVertex(PyObject* args, PyObject* kwds)
222 {
223     int vertexindex;
224         int matindex;
225
226         if (!PyArg_ParseTuple(args,"ii:getVertex",&matindex,&vertexindex))
227                 return NULL;
228         
229         RAS_TexVert* vertex = m_meshobj->GetVertex(matindex,vertexindex);
230         
231         if(vertex==NULL) {
232                 PyErr_SetString(PyExc_ValueError, "mesh.getVertex(mat_idx, vert_idx): KX_MeshProxy, could not get a vertex at the given indicies");
233                 return NULL;
234         }
235         
236         return (new KX_VertexProxy(this, vertex))->NewProxy(true);
237 }
238
239 PyObject* KX_MeshProxy::PyGetPolygon(PyObject* args, PyObject* kwds)
240 {
241     int polyindex= 1;
242         PyObject* polyob = NULL;
243
244         if (!PyArg_ParseTuple(args,"i:getPolygon",&polyindex))
245                 return NULL;
246         
247         if (polyindex<0 || polyindex >= m_meshobj->NumPolygons())
248         {
249                 PyErr_SetString(PyExc_AttributeError, "mesh.getPolygon(int): KX_MeshProxy, invalid polygon index");
250                 return NULL;
251         }
252                 
253
254         RAS_Polygon* polygon = m_meshobj->GetPolygon(polyindex);
255         if (polygon)
256         {
257                 polyob = (new KX_PolyProxy(m_meshobj, polygon))->NewProxy(true);
258         }
259         else {
260                 PyErr_SetString(PyExc_AttributeError, "mesh.getPolygon(int): KX_MeshProxy, polygon is NULL, unknown reason");
261         }
262         return polyob;
263 }
264
265 KX_PYMETHODDEF_DOC(KX_MeshProxy, reinstancePhysicsMesh,
266 "Reinstance the physics mesh.")
267 {
268 #if 0
269         //this needs to be reviewed, it is dependend on Sumo/Solid. Who is using this ?
270         if(KX_ReInstanceShapeFromMesh(m_meshobj))
271                 Py_RETURN_TRUE;
272 #endif
273         Py_RETURN_FALSE;
274 }
275
276 PyObject* KX_MeshProxy::pyattr_get_materials(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
277 {
278         KX_MeshProxy* self= static_cast<KX_MeshProxy*>(self_v);
279         
280         int tot= self->m_meshobj->NumMaterials();
281         int i;
282         
283         PyObject *materials = PyList_New( tot );
284         
285         list<RAS_MeshMaterial>::iterator mit= self->m_meshobj->GetFirstMaterial();
286         
287         
288         for(i=0; i<tot; mit++, i++) {
289                 RAS_IPolyMaterial *polymat = mit->m_bucket->GetPolyMaterial();   
290                 
291                 /* Why do we need to check for RAS_BLENDERMAT if both are cast to a (PyObject*)? - Campbell */
292                 if(polymat->GetFlag() & RAS_BLENDERMAT)          
293                 {        
294                         KX_BlenderMaterial *mat = static_cast<KX_BlenderMaterial*>(polymat);     
295                         PyList_SET_ITEM(materials, i, mat->GetProxy());
296                 }
297                 else {  
298                         KX_PolygonMaterial *mat = static_cast<KX_PolygonMaterial*>(polymat);
299                         PyList_SET_ITEM(materials, i, mat->GetProxy());
300                 }
301         }       
302         return materials;
303 }
304
305 PyObject * KX_MeshProxy::pyattr_get_numMaterials(void * selfv, const KX_PYATTRIBUTE_DEF * attrdef) {
306         KX_MeshProxy * self = static_cast<KX_MeshProxy *> (selfv);
307         return PyInt_FromLong(self->m_meshobj->NumMaterials());
308 }
309
310 PyObject * KX_MeshProxy::pyattr_get_numPolygons(void * selfv, const KX_PYATTRIBUTE_DEF * attrdef) {
311         KX_MeshProxy * self = static_cast<KX_MeshProxy *> (selfv);
312         return PyInt_FromLong(self->m_meshobj->NumPolygons());
313 }
314
315 /* a close copy of ConvertPythonToGameObject but for meshes */
316 bool ConvertPythonToMesh(PyObject * value, RAS_MeshObject **object, bool py_none_ok, const char *error_prefix)
317 {
318         if (value==NULL) {
319                 PyErr_Format(PyExc_TypeError, "%s, python pointer NULL, should never happen", error_prefix);
320                 *object = NULL;
321                 return false;
322         }
323                 
324         if (value==Py_None) {
325                 *object = NULL;
326                 
327                 if (py_none_ok) {
328                         return true;
329                 } else {
330                         PyErr_Format(PyExc_TypeError, "%s, expected KX_MeshProxy or a KX_MeshProxy name, None is invalid", error_prefix);
331                         return false;
332                 }
333         }
334         
335         if (PyString_Check(value)) {
336                 *object = (RAS_MeshObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetMeshByName(STR_String( PyString_AsString(value) ));
337                 
338                 if (*object) {
339                         return true;
340                 } else {
341                         PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_MeshProxy in this scene", error_prefix, PyString_AsString(value));
342                         return false;
343                 }
344         }
345         
346         if (PyObject_TypeCheck(value, &KX_MeshProxy::Type)) {
347                 KX_MeshProxy *kx_mesh = static_cast<KX_MeshProxy*>BGE_PROXY_REF(value);
348                 
349                 /* sets the error */
350                 if (*object==NULL) {
351                         PyErr_Format(PyExc_SystemError, "%s, " BGE_PROXY_ERROR_MSG, error_prefix);
352                         return false;
353                 }               
354                 
355                 *object = kx_mesh->GetMesh();
356                 return true;
357         }
358         
359         *object = NULL;
360         
361         if (py_none_ok) {
362                 PyErr_Format(PyExc_TypeError, "%s, expect a KX_MeshProxy, a string or None", error_prefix);
363         } else {
364                 PyErr_Format(PyExc_TypeError, "%s, expect a KX_MeshProxy or a string", error_prefix);
365         }
366         
367         return false;
368 }