remove more unneeded args, also allow ipo to animate the ref value for KX_BlenderMate...
[blender.git] / source / gameengine / Ketsji / KX_PolygonMaterial.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 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31
32 #include "KX_PolygonMaterial.h"
33
34 #include "BKE_mesh.h"
35 #include "BKE_global.h"
36 #include "BKE_image.h"
37
38 #include "DNA_material_types.h"
39 #include "DNA_texture_types.h"
40 #include "DNA_image_types.h"
41 #include "DNA_meshdata_types.h"
42
43 #include "IMB_imbuf_types.h"
44
45 #include "GPU_draw.h"
46
47 #include "MEM_guardedalloc.h"
48
49 #include "RAS_LightObject.h"
50 #include "RAS_MaterialBucket.h"
51
52 #include "KX_PyMath.h"
53
54 KX_PolygonMaterial::KX_PolygonMaterial(PyTypeObject *T) 
55                 : PyObjectPlus(T),
56                   RAS_IPolyMaterial(),
57
58         m_tface(NULL),
59         m_mcol(NULL),
60         m_material(NULL),
61         m_pymaterial(NULL),
62         m_pass(0)
63 {
64 }
65
66 void KX_PolygonMaterial::Initialize(
67                 const STR_String &texname,
68                 Material* ma,
69                 int materialindex,
70                 int tile,
71                 int tilexrep,
72                 int tileyrep,
73                 int mode,
74                 int transp,
75                 bool alpha,
76                 bool zsort,
77                 int lightlayer,
78                 struct MTFace* tface,
79                 unsigned int* mcol)
80 {
81         RAS_IPolyMaterial::Initialize(
82                                                         texname,
83                                                         ma?ma->id.name:"",
84                                                         materialindex,
85                                                         tile,
86                                                         tilexrep,
87                                                         tileyrep,
88                                                         mode,
89                                                         transp,
90                                                         alpha,
91                                                         zsort);
92         m_tface = tface;
93         m_mcol = mcol;
94         m_material = ma;
95         m_pymaterial = 0;
96         m_pass = 0;
97 }
98
99 KX_PolygonMaterial::~KX_PolygonMaterial()
100 {
101         if (m_pymaterial)
102         {
103                 Py_DECREF(m_pymaterial);
104         }
105 }
106
107 bool KX_PolygonMaterial::Activate(RAS_IRasterizer* rasty, TCachingInfo& cachingInfo) const 
108 {
109         bool dopass = false;
110         if (m_pymaterial)
111         {
112                 PyObject *pyRasty = PyCObject_FromVoidPtr((void*)rasty, NULL);  /* new reference */
113                 PyObject *pyCachingInfo = PyCObject_FromVoidPtr((void*) &cachingInfo, NULL); /* new reference */
114                 PyObject *ret = PyObject_CallMethod(m_pymaterial, "activate", "(NNO)", pyRasty, pyCachingInfo, (PyObject*) this->m_proxy);
115                 if (ret)
116                 {
117                         bool value = PyInt_AsLong(ret);
118                         Py_DECREF(ret);
119                         dopass = value;
120                 }
121                 else
122                 {
123                         PyErr_Print();
124                         PyErr_Clear();
125                         PySys_SetObject( (char *)"last_traceback", NULL);
126                 }
127         }
128         else
129         {
130                 switch (m_pass++)
131                 {
132                         case 0:
133                                 DefaultActivate(rasty, cachingInfo);
134                                 dopass = true;
135                                 break;
136                         default:
137                                 m_pass = 0;
138                                 dopass = false;
139                                 break;
140                 }
141         }
142         
143         return dopass;
144 }
145
146 void KX_PolygonMaterial::DefaultActivate(RAS_IRasterizer* rasty, TCachingInfo& cachingInfo) const 
147 {
148         if (GetCachingInfo() != cachingInfo)
149         {
150                 if (!cachingInfo)
151                         GPU_set_tpage(NULL);
152
153                 cachingInfo = GetCachingInfo();
154
155                 if ((m_drawingmode & 4)&& (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED))
156                 {
157                         Image *ima = (Image*)m_tface->tpage;
158                         GPU_update_image_time(ima, rasty->GetTime());
159                         GPU_set_tpage(m_tface);
160                 }
161                 else
162                         GPU_set_tpage(NULL);
163                 
164                 if(m_drawingmode & RAS_IRasterizer::KX_TWOSIDE)
165                         rasty->SetCullFace(false);
166                 else
167                         rasty->SetCullFace(true);
168
169                 if ((m_drawingmode & RAS_IRasterizer::KX_LINES) ||
170                     (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME))
171                         rasty->SetLines(true);
172                 else
173                         rasty->SetLines(false);
174                 rasty->SetSpecularity(m_specular[0],m_specular[1],m_specular[2],m_specularity);
175                 rasty->SetShinyness(m_shininess);
176                 rasty->SetDiffuse(m_diffuse[0], m_diffuse[1],m_diffuse[2], 1.0);
177                 if (m_material)
178                         rasty->SetPolygonOffset(-m_material->zoffs, 0.0);
179         }
180
181         //rasty->SetSpecularity(m_specular[0],m_specular[1],m_specular[2],m_specularity);
182         //rasty->SetShinyness(m_shininess);
183         //rasty->SetDiffuse(m_diffuse[0], m_diffuse[1],m_diffuse[2], 1.0);
184         //if (m_material)
185         //      rasty->SetPolygonOffset(-m_material->zoffs, 0.0);
186 }
187
188 void KX_PolygonMaterial::GetMaterialRGBAColor(unsigned char *rgba) const
189 {
190         if (m_material) {
191                 *rgba++ = (unsigned char) (m_material->r*255.0);
192                 *rgba++ = (unsigned char) (m_material->g*255.0);
193                 *rgba++ = (unsigned char) (m_material->b*255.0);
194                 *rgba++ = (unsigned char) (m_material->alpha*255.0);
195         } else
196                 RAS_IPolyMaterial::GetMaterialRGBAColor(rgba);
197 }
198
199
200 //----------------------------------------------------------------------------
201 //Python
202
203
204 PyMethodDef KX_PolygonMaterial::Methods[] = {
205         KX_PYMETHODTABLE(KX_PolygonMaterial, setCustomMaterial),
206         KX_PYMETHODTABLE(KX_PolygonMaterial, updateTexture),
207         KX_PYMETHODTABLE(KX_PolygonMaterial, setTexture),
208         KX_PYMETHODTABLE(KX_PolygonMaterial, activate),
209 //      KX_PYMETHODTABLE(KX_PolygonMaterial, setPerPixelLights),
210         
211         {NULL,NULL} //Sentinel
212 };
213
214 PyAttributeDef KX_PolygonMaterial::Attributes[] = {
215         KX_PYATTRIBUTE_RO_FUNCTION("texture",   KX_PolygonMaterial, pyattr_get_texture),
216         KX_PYATTRIBUTE_RO_FUNCTION("material",  KX_PolygonMaterial, pyattr_get_material), /* should probably be .name ? */
217         
218         KX_PYATTRIBUTE_INT_RW("tile", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_tile),
219         KX_PYATTRIBUTE_INT_RW("tilexrep", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_tilexrep),
220         KX_PYATTRIBUTE_INT_RW("tileyrep", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_tileyrep),
221         KX_PYATTRIBUTE_INT_RW("drawingmode", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_drawingmode),        
222         //KX_PYATTRIBUTE_INT_RW("lightlayer", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_lightlayer),
223
224         KX_PYATTRIBUTE_BOOL_RW("transparent", KX_PolygonMaterial, m_alpha),
225         KX_PYATTRIBUTE_BOOL_RW("zsort", KX_PolygonMaterial, m_zsort),
226         
227         KX_PYATTRIBUTE_FLOAT_RW("shininess", 0.0f, 1000.0f, KX_PolygonMaterial, m_shininess),
228         KX_PYATTRIBUTE_FLOAT_RW("specularity", 0.0f, 1000.0f, KX_PolygonMaterial, m_specularity),
229         
230         KX_PYATTRIBUTE_RW_FUNCTION("diffuse", KX_PolygonMaterial, pyattr_get_texture, pyattr_set_diffuse),
231         KX_PYATTRIBUTE_RW_FUNCTION("specular",KX_PolygonMaterial, pyattr_get_specular, pyattr_set_specular),    
232         
233         KX_PYATTRIBUTE_RO_FUNCTION("tface",     KX_PolygonMaterial, pyattr_get_tface), /* How the heck is this even useful??? - Campbell */
234         KX_PYATTRIBUTE_RO_FUNCTION("gl_texture", KX_PolygonMaterial, pyattr_get_gl_texture), /* could be called 'bindcode' */
235         
236         /* triangle used to be an attribute, removed for 2.49, nobody should be using it */
237         { NULL }        //Sentinel
238 };
239
240 PyTypeObject KX_PolygonMaterial::Type = {
241 #if (PY_VERSION_HEX >= 0x02060000)
242         PyVarObject_HEAD_INIT(NULL, 0)
243 #else
244         /* python 2.5 and below */
245         PyObject_HEAD_INIT( NULL )  /* required py macro */
246         0,                          /* ob_size */
247 #endif
248                 "KX_PolygonMaterial",
249                 sizeof(PyObjectPlus_Proxy),
250                 0,
251                 py_base_dealloc,
252                 0,
253                 0,
254                 0,
255                 0,
256                 py_base_repr,
257                 0,0,0,0,0,0,
258                 py_base_getattro,
259                 py_base_setattro,
260                 0,0,0,0,0,0,0,0,0,
261                 Methods
262 };
263
264 PyParentObject KX_PolygonMaterial::Parents[] = {
265         &KX_PolygonMaterial::Type,
266         &PyObjectPlus::Type,
267         NULL
268 };
269
270 PyObject* KX_PolygonMaterial::py_getattro(PyObject *attr)
271 {       
272         py_getattro_up(PyObjectPlus);
273 }
274
275 PyObject* KX_PolygonMaterial::py_getattro_dict() {
276         py_getattro_dict_up(PyObjectPlus);
277 }
278
279 int KX_PolygonMaterial::py_setattro(PyObject *attr, PyObject *value)
280 {
281         py_setattro_up(PyObjectPlus);
282 }
283
284 KX_PYMETHODDEF_DOC(KX_PolygonMaterial, setCustomMaterial, "setCustomMaterial(material)")
285 {
286         PyObject *material;
287         if (PyArg_ParseTuple(args, "O:setCustomMaterial", &material))
288         {
289                 if (m_pymaterial) {
290                         Py_DECREF(m_pymaterial);
291                 }
292                 m_pymaterial = material;
293                 Py_INCREF(m_pymaterial);
294                 Py_RETURN_NONE;
295         }
296         
297         return NULL;
298 }
299
300 KX_PYMETHODDEF_DOC(KX_PolygonMaterial, updateTexture, "updateTexture(tface, rasty)")
301 {
302         PyObject *pyrasty, *pytface;
303         if (PyArg_ParseTuple(args, "O!O!:updateTexture", &PyCObject_Type, &pytface, &PyCObject_Type, &pyrasty))
304         {
305                 MTFace *tface = (MTFace*) PyCObject_AsVoidPtr(pytface);
306                 RAS_IRasterizer *rasty = (RAS_IRasterizer*) PyCObject_AsVoidPtr(pyrasty);
307                 Image *ima = (Image*)tface->tpage;
308                 GPU_update_image_time(ima, rasty->GetTime());
309
310                 Py_RETURN_NONE;
311         }
312         
313         return NULL;
314 }
315
316 KX_PYMETHODDEF_DOC(KX_PolygonMaterial, setTexture, "setTexture(tface)")
317 {
318         PyObject *pytface;
319         if (PyArg_ParseTuple(args, "O!:setTexture", &PyCObject_Type, &pytface))
320         {
321                 MTFace *tface = (MTFace*) PyCObject_AsVoidPtr(pytface);
322                 GPU_set_tpage(tface);
323                 Py_RETURN_NONE;
324         }
325         
326         return NULL;
327 }
328
329 KX_PYMETHODDEF_DOC(KX_PolygonMaterial, activate, "activate(rasty, cachingInfo)")
330 {
331         PyObject *pyrasty, *pyCachingInfo;
332         if (PyArg_ParseTuple(args, "O!O!:activate", &PyCObject_Type, &pyrasty, &PyCObject_Type, &pyCachingInfo))
333         {
334                 RAS_IRasterizer *rasty = static_cast<RAS_IRasterizer*>(PyCObject_AsVoidPtr(pyrasty));
335                 TCachingInfo *cachingInfo = static_cast<TCachingInfo*>(PyCObject_AsVoidPtr(pyCachingInfo));
336                 if (rasty && cachingInfo)
337                 {
338                         DefaultActivate(rasty, *cachingInfo);
339                         Py_RETURN_NONE;
340                 }
341         }
342         
343         return NULL;
344 }
345
346 PyObject* KX_PolygonMaterial::pyattr_get_texture(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
347 {
348         KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v);
349         return PyString_FromString(self->m_texturename.ReadPtr());
350 }
351
352 PyObject* KX_PolygonMaterial::pyattr_get_material(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
353 {
354         KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v);
355         return PyString_FromString(self->m_materialname.ReadPtr());
356 }
357
358 /* this does not seem useful */
359 PyObject* KX_PolygonMaterial::pyattr_get_tface(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
360 {
361         KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v);
362         return PyCObject_FromVoidPtr(self->m_tface, NULL);
363 }
364
365 PyObject* KX_PolygonMaterial::pyattr_get_gl_texture(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
366 {
367         KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v);
368         int bindcode= 0;
369         if (self->m_tface && self->m_tface->tpage)
370                 bindcode= self->m_tface->tpage->bindcode;
371         
372         return PyInt_FromLong(bindcode);
373 }
374
375
376 PyObject* KX_PolygonMaterial::pyattr_get_diffuse(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
377 {
378         KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v);
379         return PyObjectFrom(self->m_diffuse);
380 }
381
382 int KX_PolygonMaterial::pyattr_set_diffuse(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
383 {
384         KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v);
385         MT_Vector3 vec;
386         
387         if (!PyVecTo(value, vec))
388                 return PY_SET_ATTR_FAIL;
389         
390         self->m_diffuse= vec;
391         return PY_SET_ATTR_SUCCESS;
392 }
393
394 PyObject* KX_PolygonMaterial::pyattr_get_specular(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
395 {
396         KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v);
397         return PyObjectFrom(self->m_specular);
398 }
399
400 int KX_PolygonMaterial::pyattr_set_specular(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
401 {
402         KX_PolygonMaterial* self= static_cast<KX_PolygonMaterial*>(self_v);
403         MT_Vector3 vec;
404         
405         if (!PyVecTo(value, vec))
406                 return PY_SET_ATTR_FAIL;
407         
408         self->m_specular= vec;
409         return PY_SET_ATTR_SUCCESS;
410 }