BGE Python API
[blender.git] / source / gameengine / Ketsji / KX_VertexProxy.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_VertexProxy.h"
34 #include "KX_MeshProxy.h"
35 #include "RAS_TexVert.h"
36
37 #include "KX_PyMath.h"
38
39 PyTypeObject KX_VertexProxy::Type = {
40         PyObject_HEAD_INIT(NULL)
41         0,
42         "KX_VertexProxy",
43         sizeof(KX_VertexProxy),
44         0,
45         PyDestructor,
46         0,
47         0,
48         0,
49         0,
50         py_base_repr,
51         0,0,0,0,0,0,
52         py_base_getattro,
53         py_base_setattro,
54         0,0,0,0,0,0,0,0,0,
55         Methods
56 };
57
58 PyParentObject KX_VertexProxy::Parents[] = {
59         &KX_VertexProxy::Type,
60         &SCA_IObject::Type,
61         &CValue::Type,
62         NULL
63 };
64
65 PyMethodDef KX_VertexProxy::Methods[] = {
66 {"getXYZ", (PyCFunction)KX_VertexProxy::sPyGetXYZ,METH_NOARGS},
67 {"setXYZ", (PyCFunction)KX_VertexProxy::sPySetXYZ,METH_O},
68 {"getUV", (PyCFunction)KX_VertexProxy::sPyGetUV,METH_NOARGS},
69 {"setUV", (PyCFunction)KX_VertexProxy::sPySetUV,METH_O},
70
71 {"getUV2", (PyCFunction)KX_VertexProxy::sPyGetUV2,METH_NOARGS},
72 {"setUV2", (PyCFunction)KX_VertexProxy::sPySetUV2,METH_VARARGS},
73
74 {"getRGBA", (PyCFunction)KX_VertexProxy::sPyGetRGBA,METH_NOARGS},
75 {"setRGBA", (PyCFunction)KX_VertexProxy::sPySetRGBA,METH_O},
76 {"getNormal", (PyCFunction)KX_VertexProxy::sPyGetNormal,METH_NOARGS},
77 {"setNormal", (PyCFunction)KX_VertexProxy::sPySetNormal,METH_O},
78   {NULL,NULL} //Sentinel
79 };
80
81 PyAttributeDef KX_VertexProxy::Attributes[] = {
82         
83         KX_PYATTRIBUTE_DUMMY("x"),
84         KX_PYATTRIBUTE_DUMMY("y"),
85         KX_PYATTRIBUTE_DUMMY("z"),
86         
87         KX_PYATTRIBUTE_DUMMY("r"),
88         KX_PYATTRIBUTE_DUMMY("g"),
89         KX_PYATTRIBUTE_DUMMY("b"),
90         KX_PYATTRIBUTE_DUMMY("a"),
91         
92         KX_PYATTRIBUTE_DUMMY("u"),
93         KX_PYATTRIBUTE_DUMMY("v"),
94         
95         KX_PYATTRIBUTE_DUMMY("u2"),
96         KX_PYATTRIBUTE_DUMMY("v2"),
97         
98         KX_PYATTRIBUTE_DUMMY("XYZ"),
99         KX_PYATTRIBUTE_DUMMY("UV"),
100         
101         KX_PYATTRIBUTE_DUMMY("color"),
102         KX_PYATTRIBUTE_DUMMY("colour"),
103         
104         KX_PYATTRIBUTE_DUMMY("normal"),
105         
106         { NULL }        //Sentinel
107 };
108
109 PyObject*
110 KX_VertexProxy::py_getattro(PyObject *attr)
111 {
112   char *attr_str= PyString_AsString(attr);
113   if (attr_str[1]=='\0') { // Group single letters
114     // pos
115     if (attr_str[0]=='x')
116         return PyFloat_FromDouble(m_vertex->getXYZ()[0]);
117     if (attr_str[0]=='y')
118         return PyFloat_FromDouble(m_vertex->getXYZ()[1]);
119     if (attr_str[0]=='z')
120         return PyFloat_FromDouble(m_vertex->getXYZ()[2]);
121
122     // Col
123     if (attr_str[0]=='r')
124         return PyFloat_FromDouble(m_vertex->getRGBA()[0]/255.0);
125     if (attr_str[0]=='g')
126         return PyFloat_FromDouble(m_vertex->getRGBA()[1]/255.0);
127     if (attr_str[0]=='b')
128         return PyFloat_FromDouble(m_vertex->getRGBA()[2]/255.0);
129     if (attr_str[0]=='a')
130         return PyFloat_FromDouble(m_vertex->getRGBA()[3]/255.0);
131
132     // UV
133     if (attr_str[0]=='u')
134         return PyFloat_FromDouble(m_vertex->getUV1()[0]);
135     if (attr_str[0]=='v')
136         return PyFloat_FromDouble(m_vertex->getUV1()[1]);
137   }
138   
139   
140   if (!strcmp(attr_str, "XYZ"))
141         return PyObjectFrom(MT_Vector3(m_vertex->getXYZ()));
142
143   if (!strcmp(attr_str, "UV"))
144         return PyObjectFrom(MT_Point2(m_vertex->getUV1()));
145
146   if (!strcmp(attr_str, "color") || !strcmp(attr_str, "colour"))
147   {
148         const unsigned char *colp = m_vertex->getRGBA();
149         MT_Vector4 color(colp[0], colp[1], colp[2], colp[3]);
150         color /= 255.0;
151         return PyObjectFrom(color);
152   }
153   
154   if (!strcmp(attr_str, "normal"))
155   {
156         return PyObjectFrom(MT_Vector3(m_vertex->getNormal()));
157   }
158   
159   py_getattro_up(SCA_IObject);
160 }
161
162 int    KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue)
163 {
164   char *attr_str= PyString_AsString(attr);
165   if (PySequence_Check(pyvalue))
166   {
167         if (!strcmp(attr_str, "XYZ"))
168         {
169                 MT_Point3 vec;
170                 if (PyVecTo(pyvalue, vec))
171                 {
172                         m_vertex->SetXYZ(vec);
173                         m_mesh->SetMeshModified(true);
174                         return PY_SET_ATTR_SUCCESS;
175                 }
176                 return PY_SET_ATTR_FAIL;
177         }
178         
179         if (!strcmp(attr_str, "UV"))
180         {
181                 MT_Point2 vec;
182                 if (PyVecTo(pyvalue, vec))
183                 {
184                         m_vertex->SetUV(vec);
185                         m_mesh->SetMeshModified(true);
186                         return PY_SET_ATTR_SUCCESS;
187                 }
188                 return PY_SET_ATTR_FAIL;
189         }
190         
191         if (!strcmp(attr_str, "color") || !strcmp(attr_str, "colour"))
192         {
193                 MT_Vector4 vec;
194                 if (PyVecTo(pyvalue, vec))
195                 {
196                         m_vertex->SetRGBA(vec);
197                         m_mesh->SetMeshModified(true);
198                         return PY_SET_ATTR_SUCCESS;
199                 }
200                 return PY_SET_ATTR_FAIL;
201         }
202         
203         if (!strcmp(attr_str, "normal"))
204         {
205                 MT_Vector3 vec;
206                 if (PyVecTo(pyvalue, vec))
207                 {
208                         m_vertex->SetNormal(vec);
209                         m_mesh->SetMeshModified(true);
210                         return PY_SET_ATTR_SUCCESS;
211                 }
212                 return PY_SET_ATTR_FAIL;
213         }
214   }
215   
216   if (PyFloat_Check(pyvalue))
217   {
218         float val = PyFloat_AsDouble(pyvalue);
219         // pos
220         MT_Point3 pos(m_vertex->getXYZ());
221         if (!strcmp(attr_str, "x"))
222         {
223                 pos.x() = val;
224                 m_vertex->SetXYZ(pos);
225                 m_mesh->SetMeshModified(true);
226                 return PY_SET_ATTR_SUCCESS;
227         }
228         
229         if (!strcmp(attr_str, "y"))
230         {
231                 pos.y() = val;
232                 m_vertex->SetXYZ(pos);
233                 m_mesh->SetMeshModified(true);
234                 return PY_SET_ATTR_SUCCESS;
235         }
236         
237         if (!strcmp(attr_str, "z"))
238         {
239                 pos.z() = val;
240                 m_vertex->SetXYZ(pos);
241                 m_mesh->SetMeshModified(true);
242                 return PY_SET_ATTR_SUCCESS;
243         }
244         
245         // uv
246         MT_Point2 uv = m_vertex->getUV1();
247         if (!strcmp(attr_str, "u"))
248         {
249                 uv[0] = val;
250                 m_vertex->SetUV(uv);
251                 m_mesh->SetMeshModified(true);
252                 return PY_SET_ATTR_SUCCESS;
253         }
254
255         if (!strcmp(attr_str, "v"))
256         {
257                 uv[1] = val;
258                 m_vertex->SetUV(uv);
259                 m_mesh->SetMeshModified(true);
260                 return PY_SET_ATTR_SUCCESS;
261         }
262
263         // uv
264         MT_Point2 uv2 = m_vertex->getUV2();
265         if (!strcmp(attr_str, "u2"))
266         {
267                 uv[0] = val;
268                 m_vertex->SetUV2(uv);
269                 m_mesh->SetMeshModified(true);
270                 return 0;
271         }
272
273         if (!strcmp(attr_str, "v2"))
274         {
275                 uv[1] = val;
276                 m_vertex->SetUV2(uv);
277                 m_mesh->SetMeshModified(true);
278                 return PY_SET_ATTR_SUCCESS;
279         }
280         
281         // col
282         unsigned int icol = *((const unsigned int *)m_vertex->getRGBA());
283         unsigned char *cp = (unsigned char*) &icol;
284         val *= 255.0;
285         if (!strcmp(attr_str, "r"))
286         {
287                 cp[0] = (unsigned char) val;
288                 m_vertex->SetRGBA(icol);
289                 m_mesh->SetMeshModified(true);
290                 return PY_SET_ATTR_SUCCESS;
291         }
292         if (!strcmp(attr_str, "g"))
293         {
294                 cp[1] = (unsigned char) val;
295                 m_vertex->SetRGBA(icol);
296                 m_mesh->SetMeshModified(true);
297                 return PY_SET_ATTR_SUCCESS;
298         }
299         if (!strcmp(attr_str, "b"))
300         {
301                 cp[2] = (unsigned char) val;
302                 m_vertex->SetRGBA(icol);
303                 m_mesh->SetMeshModified(true);
304                 return PY_SET_ATTR_SUCCESS;
305         }
306         if (!strcmp(attr_str, "a"))
307         {
308                 cp[3] = (unsigned char) val;
309                 m_vertex->SetRGBA(icol);
310                 m_mesh->SetMeshModified(true);
311                 return PY_SET_ATTR_SUCCESS;
312         }
313   }
314   
315   return SCA_IObject::py_setattro(attr, pyvalue);
316 }
317
318 KX_VertexProxy::KX_VertexProxy(KX_MeshProxy*mesh, RAS_TexVert* vertex)
319 :       m_vertex(vertex),
320         m_mesh(mesh)
321 {
322 }
323
324 KX_VertexProxy::~KX_VertexProxy()
325 {
326 }
327
328
329
330 // stuff for cvalue related things
331 CValue*         KX_VertexProxy::Calc(VALUE_OPERATOR, CValue *) { return NULL;}
332 CValue*         KX_VertexProxy::CalcFinal(VALUE_DATA_TYPE, VALUE_OPERATOR, CValue *) { return NULL;}    
333 STR_String      sVertexName="vertex";
334 const STR_String &      KX_VertexProxy::GetText() {return sVertexName;};
335 double          KX_VertexProxy::GetNumber() { return -1;}
336 STR_String      KX_VertexProxy::GetName() { return sVertexName;}
337 void            KX_VertexProxy::SetName(STR_String) { };
338 CValue*         KX_VertexProxy::GetReplica() { return NULL;}
339 void            KX_VertexProxy::ReplicaSetName(STR_String) {};
340
341
342 // stuff for python integration
343         
344 PyObject* KX_VertexProxy::PyGetXYZ(PyObject*)
345 {
346         return PyObjectFrom(MT_Point3(m_vertex->getXYZ()));
347 }
348
349 PyObject* KX_VertexProxy::PySetXYZ(PyObject*, PyObject* value)
350 {
351         MT_Point3 vec;
352         if (!PyVecTo(value, vec))
353                 return NULL;
354                 
355         m_vertex->SetXYZ(vec);
356         m_mesh->SetMeshModified(true);
357         Py_RETURN_NONE;
358 }
359
360 PyObject* KX_VertexProxy::PyGetNormal(PyObject*)
361 {
362         return PyObjectFrom(MT_Vector3(m_vertex->getNormal()));
363 }
364
365 PyObject* KX_VertexProxy::PySetNormal(PyObject*, PyObject* value)
366 {
367         MT_Vector3 vec;
368         if (!PyVecTo(value, vec))
369                 return NULL;
370         
371         m_vertex->SetNormal(vec);
372         m_mesh->SetMeshModified(true);
373         Py_RETURN_NONE;
374 }
375
376
377 PyObject* KX_VertexProxy::PyGetRGBA(PyObject*)
378 {
379         int *rgba = (int *) m_vertex->getRGBA();
380         return PyInt_FromLong(*rgba);
381 }
382
383 PyObject* KX_VertexProxy::PySetRGBA(PyObject*, PyObject* value)
384 {
385         if PyInt_Check(value) {
386                 int rgba = PyInt_AsLong(value);
387                 m_vertex->SetRGBA(rgba);
388                 m_mesh->SetMeshModified(true);
389                 Py_RETURN_NONE;
390         }
391         else {  
392                 MT_Vector4 vec;
393                 if (PyVecTo(value, vec))
394                 {
395                         m_vertex->SetRGBA(vec);
396                         m_mesh->SetMeshModified(true);
397                         Py_RETURN_NONE;
398                 }
399         }
400         
401         PyErr_SetString(PyExc_TypeError, "expected a 4D vector or an int");
402         return NULL;
403 }
404
405
406 PyObject* KX_VertexProxy::PyGetUV(PyObject*)
407 {
408         return PyObjectFrom(MT_Vector2(m_vertex->getUV1()));
409 }
410
411 PyObject* KX_VertexProxy::PySetUV(PyObject*, PyObject* value)
412 {
413         MT_Point2 vec;
414         if (!PyVecTo(value, vec))
415                 return NULL;
416         
417         m_vertex->SetUV(vec);
418         m_mesh->SetMeshModified(true);
419         Py_RETURN_NONE;
420 }
421
422 PyObject* KX_VertexProxy::PyGetUV2(PyObject*)
423 {
424         return PyObjectFrom(MT_Vector2(m_vertex->getUV2()));
425 }
426
427 PyObject* KX_VertexProxy::PySetUV2(PyObject*, PyObject* args)
428 {
429         MT_Point2 vec;
430         unsigned int unit=0;
431         PyObject* list= NULL;
432         if(!PyArg_ParseTuple(args, "Oi:setUV2", &list, &unit))
433                 return NULL;
434         
435         if (!PyVecTo(list, vec))
436                 return NULL;
437         
438         m_vertex->SetFlag((m_vertex->getFlag()|RAS_TexVert::SECOND_UV));
439         m_vertex->SetUnit(unit);
440         m_vertex->SetUV2(vec);
441         m_mesh->SetMeshModified(true);
442         Py_RETURN_NONE;
443 }