2.50: svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r19323...
[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         PyObject_HEAD_INIT(NULL)
50         0,
51         "KX_MeshProxy",
52         sizeof(PyObjectPlus_Proxy),
53         0,
54         py_base_dealloc,
55         0,
56         0,
57         0,
58         0,
59         py_base_repr,
60         0,0,0,0,0,0,
61         py_base_getattro,
62         py_base_setattro,
63         0,0,0,0,0,0,0,0,0,
64         Methods
65 };
66
67 PyParentObject KX_MeshProxy::Parents[] = {
68         &KX_MeshProxy::Type,
69         &SCA_IObject::Type,
70         &CValue::Type,
71         &PyObjectPlus::Type,
72         NULL
73 };
74
75 PyMethodDef KX_MeshProxy::Methods[] = {
76 // Deprecated ----->
77 {"getNumMaterials", (PyCFunction)KX_MeshProxy::sPyGetNumMaterials,METH_VARARGS},
78 {"getNumPolygons", (PyCFunction)KX_MeshProxy::sPyGetNumPolygons,METH_NOARGS},
79 // <-----
80
81 {"getMaterialName", (PyCFunction)KX_MeshProxy::sPyGetMaterialName,METH_VARARGS},
82 {"getTextureName", (PyCFunction)KX_MeshProxy::sPyGetTextureName,METH_VARARGS},
83 {"getVertexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetVertexArrayLength,METH_VARARGS},
84 {"getVertex", (PyCFunction)KX_MeshProxy::sPyGetVertex,METH_VARARGS},
85 {"getPolygon", (PyCFunction)KX_MeshProxy::sPyGetPolygon,METH_VARARGS},
86 KX_PYMETHODTABLE(KX_MeshProxy, reinstancePhysicsMesh),
87 //{"getIndexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetIndexArrayLength,METH_VARARGS},
88
89   {NULL,NULL} //Sentinel
90 };
91
92 PyAttributeDef KX_MeshProxy::Attributes[] = {
93         KX_PYATTRIBUTE_RO_FUNCTION("materials",         KX_MeshProxy, pyattr_get_materials),
94         KX_PYATTRIBUTE_RO_FUNCTION("numPolygons",       KX_MeshProxy, pyattr_get_numPolygons),
95         KX_PYATTRIBUTE_RO_FUNCTION("numMaterials",      KX_MeshProxy, pyattr_get_numMaterials),
96
97         { NULL }        //Sentinel
98 };
99
100 void KX_MeshProxy::SetMeshModified(bool v)
101 {
102         m_meshobj->SetMeshModified(v);
103 }
104
105
106 PyObject* KX_MeshProxy::py_getattro(PyObject *attr)
107 {
108         py_getattro_up(SCA_IObject);
109 }
110
111 int KX_MeshProxy::py_setattro(PyObject *attr, PyObject* value)
112 {
113         py_setattro_up(SCA_IObject);
114 }
115
116
117 KX_MeshProxy::KX_MeshProxy(RAS_MeshObject* mesh)
118         : SCA_IObject(&Type), m_meshobj(mesh)
119 {
120 }
121
122 KX_MeshProxy::~KX_MeshProxy()
123 {
124 }
125
126
127
128 // stuff for cvalue related things
129 CValue*         KX_MeshProxy::Calc(VALUE_OPERATOR op, CValue *val) { return NULL;}
130 CValue*         KX_MeshProxy::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val) { return NULL;}  
131
132 const STR_String &      KX_MeshProxy::GetText() {return m_meshobj->GetName();};
133 double          KX_MeshProxy::GetNumber() { return -1;}
134 STR_String      KX_MeshProxy::GetName() { return m_meshobj->GetName();}
135 void            KX_MeshProxy::SetName(STR_String name) { };
136 CValue*         KX_MeshProxy::GetReplica() { return NULL;}
137 void            KX_MeshProxy::ReplicaSetName(STR_String name) {};
138
139
140 // stuff for python integration
141         
142 PyObject* KX_MeshProxy::PyGetNumMaterials(PyObject* args, PyObject* kwds)
143 {
144         int num = m_meshobj->NumMaterials();
145         ShowDeprecationWarning("getNumMaterials()", "the numMaterials property");
146         return PyInt_FromLong(num);
147 }
148
149 PyObject* KX_MeshProxy::PyGetNumPolygons()
150 {
151         int num = m_meshobj->NumPolygons();
152         ShowDeprecationWarning("getNumPolygons()", "the numPolygons property");
153         return PyInt_FromLong(num);
154 }
155
156 PyObject* KX_MeshProxy::PyGetMaterialName(PyObject* args, PyObject* kwds)
157 {
158     int matid= 1;
159         STR_String matname;
160
161         if (PyArg_ParseTuple(args,"i:getMaterialName",&matid))
162         {
163                 matname = m_meshobj->GetMaterialName(matid);
164         }
165         else {
166                 return NULL;
167         }
168
169         return PyString_FromString(matname.Ptr());
170                 
171 }
172         
173
174 PyObject* KX_MeshProxy::PyGetTextureName(PyObject* args, PyObject* kwds)
175 {
176     int matid= 1;
177         STR_String matname;
178
179         if (PyArg_ParseTuple(args,"i:getTextureName",&matid))
180         {
181                 matname = m_meshobj->GetTextureName(matid);
182         }
183         else {
184                 return NULL;
185         }
186
187         return PyString_FromString(matname.Ptr());
188                 
189 }
190
191 PyObject* KX_MeshProxy::PyGetVertexArrayLength(PyObject* args, PyObject* kwds)
192 {
193     int matid= 0;
194         int length = 0;
195
196         
197         if (!PyArg_ParseTuple(args,"i:getVertexArrayLength",&matid))
198                 return NULL;
199         
200
201         RAS_MeshMaterial *mmat = m_meshobj->GetMeshMaterial(matid); /* can be NULL*/
202         
203         if (mmat)
204         {
205                 RAS_IPolyMaterial* mat = mmat->m_bucket->GetPolyMaterial();
206                 if (mat)
207                         length = m_meshobj->NumVertices(mat);
208         }
209         
210         return PyInt_FromLong(length);
211 }
212
213
214 PyObject* KX_MeshProxy::PyGetVertex(PyObject* args, PyObject* kwds)
215 {
216     int vertexindex= 1;
217         int matindex= 1;
218         PyObject* vertexob = NULL;
219
220         if (PyArg_ParseTuple(args,"ii:getVertex",&matindex,&vertexindex))
221         {
222                 RAS_TexVert* vertex = m_meshobj->GetVertex(matindex,vertexindex);
223                 if (vertex)
224                 {
225                         vertexob = (new KX_VertexProxy(this, vertex))->NewProxy(true);
226                 }
227         }
228         else {
229                 return NULL;
230         }
231
232         return vertexob;
233                 
234 }
235
236 PyObject* KX_MeshProxy::PyGetPolygon(PyObject* args, PyObject* kwds)
237 {
238     int polyindex= 1;
239         PyObject* polyob = NULL;
240
241         if (!PyArg_ParseTuple(args,"i:getPolygon",&polyindex))
242                 return NULL;
243         
244         if (polyindex<0 || polyindex >= m_meshobj->NumPolygons())
245         {
246                 PyErr_SetString(PyExc_AttributeError, "mesh.getPolygon(int): KX_MeshProxy, invalid polygon index");
247                 return NULL;
248         }
249                 
250
251         RAS_Polygon* polygon = m_meshobj->GetPolygon(polyindex);
252         if (polygon)
253         {
254                 polyob = (new KX_PolyProxy(m_meshobj, polygon))->NewProxy(true);
255         }
256         else {
257                 PyErr_SetString(PyExc_AttributeError, "mesh.getPolygon(int): KX_MeshProxy, polygon is NULL, unknown reason");
258         }
259         return polyob;
260 }
261
262 KX_PYMETHODDEF_DOC(KX_MeshProxy, reinstancePhysicsMesh,
263 "Reinstance the physics mesh.")
264 {
265         //this needs to be reviewed, it is dependend on Sumo/Solid. Who is using this ?
266         Py_RETURN_NONE;//(KX_ReInstanceShapeFromMesh(m_meshobj)) ? Py_RETURN_TRUE : Py_RETURN_FALSE;
267 }
268
269 PyObject* KX_MeshProxy::pyattr_get_materials(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
270 {
271         KX_MeshProxy* self= static_cast<KX_MeshProxy*>(self_v);
272         
273         int tot= self->m_meshobj->NumMaterials();
274         int i;
275         
276         PyObject *materials = PyList_New( tot );
277         
278         list<RAS_MeshMaterial>::iterator mit= self->m_meshobj->GetFirstMaterial();
279         
280         
281         for(i=0; i<tot; mit++, i++) {
282                 RAS_IPolyMaterial *polymat = mit->m_bucket->GetPolyMaterial();   
283                 
284                 /* Why do we need to check for RAS_BLENDERMAT if both are cast to a (PyObject*)? - Campbell */
285                 if(polymat->GetFlag() & RAS_BLENDERMAT)          
286                 {        
287                         KX_BlenderMaterial *mat = static_cast<KX_BlenderMaterial*>(polymat);     
288                         PyList_SET_ITEM(materials, i, mat->GetProxy());
289                 }
290                 else {  
291                         KX_PolygonMaterial *mat = static_cast<KX_PolygonMaterial*>(polymat);
292                         PyList_SET_ITEM(materials, i, mat->GetProxy());
293                 }
294         }       
295         return materials;
296 }
297
298 PyObject * KX_MeshProxy::pyattr_get_numMaterials(void * selfv, const KX_PYATTRIBUTE_DEF * attrdef) {
299         KX_MeshProxy * self = static_cast<KX_MeshProxy *> (selfv);
300         return PyInt_FromLong(self->m_meshobj->NumMaterials());
301 }
302
303 PyObject * KX_MeshProxy::pyattr_get_numPolygons(void * selfv, const KX_PYATTRIBUTE_DEF * attrdef) {
304         KX_MeshProxy * self = static_cast<KX_MeshProxy *> (selfv);
305         return PyInt_FromLong(self->m_meshobj->NumPolygons());
306 }
307
308 /* a close copy of ConvertPythonToGameObject but for meshes */
309 bool ConvertPythonToMesh(PyObject * value, RAS_MeshObject **object, bool py_none_ok, const char *error_prefix)
310 {
311         if (value==NULL) {
312                 PyErr_Format(PyExc_TypeError, "%s, python pointer NULL, should never happen", error_prefix);
313                 *object = NULL;
314                 return false;
315         }
316                 
317         if (value==Py_None) {
318                 *object = NULL;
319                 
320                 if (py_none_ok) {
321                         return true;
322                 } else {
323                         PyErr_Format(PyExc_TypeError, "%s, expected KX_MeshProxy or a KX_MeshProxy name, None is invalid", error_prefix);
324                         return false;
325                 }
326         }
327         
328         if (PyString_Check(value)) {
329                 *object = (RAS_MeshObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetMeshByName(STR_String( PyString_AsString(value) ));
330                 
331                 if (*object) {
332                         return true;
333                 } else {
334                         PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_MeshProxy in this scene", error_prefix, PyString_AsString(value));
335                         return false;
336                 }
337         }
338         
339         if (PyObject_TypeCheck(value, &KX_MeshProxy::Type)) {
340                 KX_MeshProxy *kx_mesh = static_cast<KX_MeshProxy*>BGE_PROXY_REF(value);
341                 
342                 /* sets the error */
343                 if (*object==NULL) {
344                         PyErr_Format(PyExc_RuntimeError, "%s, " BGE_PROXY_ERROR_MSG, error_prefix);
345                         return false;
346                 }               
347                 
348                 *object = kx_mesh->GetMesh();
349                 return true;
350         }
351         
352         *object = NULL;
353         
354         if (py_none_ok) {
355                 PyErr_Format(PyExc_TypeError, "%s, expect a KX_MeshProxy, a string or None", error_prefix);
356         } else {
357                 PyErr_Format(PyExc_TypeError, "%s, expect a KX_MeshProxy or a string", error_prefix);
358         }
359         
360         return false;
361 }