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