patch by Charlie, related to recent changes of multi-uv/lightmap generation. This...
[blender-staging.git] / source / gameengine / Ketsji / KX_BlenderMaterial.cpp
1
2 // ------------------------------------
3 // ...
4 // ------------------------------------
5 #ifdef HAVE_CONFIG_H
6 #include <config.h>
7 #endif
8
9 #ifdef WIN32
10 #include <windows.h>
11 #endif // WIN32
12 #ifdef __APPLE__
13 #define GL_GLEXT_LEGACY 1
14 #include <OpenGL/gl.h>
15 #include <OpenGL/glu.h>
16 #else
17 #include <GL/gl.h>
18 #include <GL/glu.h>
19 #endif
20
21 #include "KX_BlenderMaterial.h"
22 #include "BL_Material.h"
23 #include "KX_Scene.h"
24 #include "KX_Light.h"
25 #include "KX_GameObject.h"
26 #include "KX_MeshProxy.h"
27
28 #include "MT_Vector3.h"
29 #include "MT_Vector4.h"
30 #include "MT_Matrix4x4.h"
31
32 #include "RAS_MeshObject.h"
33 #include "RAS_IRasterizer.h"
34 #include "RAS_OpenGLRasterizer/RAS_GLExtensionManager.h"
35 #include "RAS_OpenGLRasterizer/ARB_multitexture.h"
36
37 extern "C" {
38 #include "BDR_drawmesh.h"
39 }
40
41 #include "STR_HashedString.h"
42
43 // ------------------------------------
44 #include "DNA_object_types.h"
45 #include "DNA_material_types.h"
46 #include "DNA_image_types.h"
47 #include "DNA_meshdata_types.h"
48 #include "BKE_mesh.h"
49 // ------------------------------------
50 using namespace bgl;
51 #define spit(x) std::cout << x << std::endl;
52
53 //static PyObject *gTextureDict = 0;
54
55 KX_BlenderMaterial::KX_BlenderMaterial(
56     KX_Scene *scene,
57         BL_Material *data,
58         bool skin,
59         int lightlayer,
60         void *clientobject,
61         PyTypeObject *T
62         )
63 :       PyObjectPlus(T),
64         RAS_IPolyMaterial(
65                 STR_String( data->texname[0] ),
66                 STR_String( data->matname ), // needed for physics!
67                 data->tile,
68                 data->tilexrep[0],
69                 data->tileyrep[0],
70                 data->mode,
71                 ((data->ras_mode &TRANSP)!=0),
72                 ((data->ras_mode &ZSORT)!=0),
73                 lightlayer,
74                 ((data->ras_mode &TRIANGLE)!=0),
75                 clientobject
76         ),
77         mMaterial(data),
78         mShader(0),
79         mScene(scene),
80         mUserDefBlend(0),
81         mModified(0),
82         mPass(0)
83
84 {
85         // --------------------------------
86         // RAS_IPolyMaterial variables... 
87         m_flag |=RAS_BLENDERMAT;
88         m_flag |=(mMaterial->IdMode>=ONETEX)?RAS_MULTITEX:0;
89         m_flag |=(mMaterial->ras_mode & USE_LIGHT)!=0?RAS_MULTILIGHT:0;
90         m_flag |=(mMaterial->ras_mode &ALPHA_TEST)!=0?RAS_FORCEALPHA:0;
91
92         // figure max
93         int enabled = mMaterial->num_enabled;
94         int max = BL_Texture::GetMaxUnits();
95         mMaterial->num_enabled = enabled>=max?max:enabled;
96
97         // base class
98         m_enabled = mMaterial->num_enabled;
99
100         // test the sum of the various modes for equality
101         // so we can ether accept or reject this material 
102         // as being equal, this is rather important to 
103         // prevent material bleeding
104         for(int i=0; i<mMaterial->num_enabled; i++) {
105                 m_multimode     +=
106                         ( mMaterial->flag[i]    +
107                           mMaterial->blend_mode[i]
108                          );
109         }
110         m_multimode += mMaterial->IdMode+mMaterial->ras_mode;
111
112 }
113
114 KX_BlenderMaterial::~KX_BlenderMaterial()
115 {
116         // cleanup work
117         OnExit();
118 }
119
120
121 MTFace* KX_BlenderMaterial::GetMTFace(void) const 
122 {
123         // fonts on polys
124         MT_assert(mMaterial->tface);
125         return mMaterial->tface;
126 }
127
128 unsigned int* KX_BlenderMaterial::GetMCol(void) const 
129 {
130         // fonts on polys
131         return mMaterial->rgb;
132 }
133
134 void KX_BlenderMaterial::OnConstruction()
135 {
136         // for each unique material...
137         int i;
138         for(i=0; i<mMaterial->num_enabled; i++) {
139                 BL_Texture::ActivateUnit(i);
140                 if( mMaterial->mapping[i].mapping & USEENV ) {
141                         if(!RAS_EXT_support._ARB_texture_cube_map) {
142                                 spit("CubeMap textures not supported");
143                                 continue;
144                         }
145                         if(!mTextures[i].InitCubeMap(i, mMaterial->cubemap[i] ) )
146                                 spit("unable to initialize image("<<i<<") in "<< 
147                                                 mMaterial->matname<< ", image will not be available");
148                 } 
149         
150                 else {
151                         if( mMaterial->img[i] ) {
152                                 if( ! mTextures[i].InitFromImage(i, mMaterial->img[i], (mMaterial->flag[i] &MIPMAP)!=0 ))
153                                         spit("unable to initialize image("<<i<<") in "<< 
154                                                  mMaterial->matname<< ", image will not be available");
155                         }
156                 }
157         }
158         mBlendFunc[0] =0;
159         mBlendFunc[1] =0;
160 }
161
162 void KX_BlenderMaterial::OnExit()
163 {
164         if( mShader ) {
165                  //note, the shader here is allocated, per unique material
166                  //and this function is called per face
167                 mShader->SetProg(0);
168                 delete mShader;
169                 mShader = 0;
170         }
171
172         BL_Texture::ActivateFirst();
173         for(int i=0; i<mMaterial->num_enabled; i++) {
174                 BL_Texture::ActivateUnit(i);
175                 mTextures[i].DeleteTex();
176                 mTextures[i].DisableUnit();
177         }
178
179         if( mMaterial->tface ) 
180                 set_tpage(mMaterial->tface);
181 }
182
183
184 void KX_BlenderMaterial::setShaderData( bool enable, RAS_IRasterizer *ras)
185 {
186         MT_assert(RAS_EXT_support._ARB_shader_objects && mShader);
187
188         int i;
189         if( !enable || !mShader->Ok() ) {
190                 // frame cleanup.
191                 mShader->SetProg(false);
192                 BL_Texture::DisableAllTextures();
193                 return;
194         }
195
196         BL_Texture::DisableAllTextures();
197         mShader->SetProg(true);
198         
199         BL_Texture::ActivateFirst();
200
201         mShader->ApplyShader();
202
203         // for each enabled unit
204         for(i=0; i<mMaterial->num_enabled; i++) {
205                 if(!mTextures[i].Ok()) continue;
206                 mTextures[i].ActivateTexture();
207                 mTextures[0].SetMapping(mMaterial->mapping[i].mapping);
208         }
209
210         if(!mUserDefBlend) {
211                 setDefaultBlending();
212         }
213         else {
214                 // tested to be valid enums
215                 glEnable(GL_BLEND);
216                 glBlendFunc(mBlendFunc[0], mBlendFunc[1]);
217         }
218 }
219
220
221 void KX_BlenderMaterial::setTexData( bool enable, RAS_IRasterizer *ras)
222 {
223         if(RAS_EXT_support._ARB_shader_objects && mShader) 
224                 mShader->SetProg(false);
225
226         BL_Texture::DisableAllTextures();
227         if( !enable )
228                 return;
229
230         BL_Texture::ActivateFirst();
231
232         if( mMaterial->IdMode == DEFAULT_BLENDER ) {
233                 setDefaultBlending();
234                 return;
235         }
236
237         if( mMaterial->IdMode == TEXFACE ) {
238                 // no material connected to the object
239                 if( mTextures[0].Ok() ) {
240                         mTextures[0].ActivateTexture();
241                         mTextures[0].setTexEnv(0, true);
242                         mTextures[0].SetMapping(mMaterial->mapping[0].mapping);
243                         setDefaultBlending(); 
244                 }
245                 return;
246         }
247
248         int mode = 0,i=0;
249         for(i=0; (i<mMaterial->num_enabled); i++) {
250                 if( !mTextures[i].Ok() ) continue;
251
252                 mTextures[i].ActivateTexture();
253                 mTextures[i].setTexEnv(mMaterial);
254                 mode = mMaterial->mapping[i].mapping;
255
256                 if(mode &USEOBJ)
257                         setObjectMatrixData(i, ras);
258                 else
259                         mTextures[i].SetMapping(mode);
260                 
261                 if(!(mode &USEOBJ))
262                         setTexMatrixData( i );
263         }
264
265         if(!mUserDefBlend) {
266                 setDefaultBlending();
267         }
268         else {
269                 glEnable(GL_BLEND);
270                 glBlendFunc(mBlendFunc[0], mBlendFunc[1]);
271         }
272 }
273
274 void
275 KX_BlenderMaterial::ActivatShaders(
276         RAS_IRasterizer* rasty, 
277         TCachingInfo& cachingInfo)const
278 {
279         KX_BlenderMaterial *tmp = const_cast<KX_BlenderMaterial*>(this);
280
281         // reset... 
282         if(tmp->mMaterial->IsShared()) 
283                 cachingInfo =0;
284         
285         if (GetCachingInfo() != cachingInfo) {
286
287                 if (!cachingInfo)
288                         tmp->setShaderData( false, rasty);
289                 
290                 cachingInfo = GetCachingInfo();
291         
292                 if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED ) {
293                         tmp->setShaderData( true, rasty);
294                         rasty->EnableTextures(true);
295                 }
296                 else {
297                         tmp->setShaderData( false, rasty);
298                         rasty->EnableTextures(false);
299                 }
300
301                 if(mMaterial->mode & RAS_IRasterizer::KX_TWOSIDE)
302                         rasty->SetCullFace(false);
303                 else
304                         rasty->SetCullFace(true);
305
306                 if (((mMaterial->ras_mode &WIRE)!=0) || mMaterial->mode & RAS_IRasterizer::KX_LINES)
307                 {               
308                         if((mMaterial->ras_mode &WIRE)!=0) 
309                                 rasty->SetCullFace(false);
310                         rasty->SetLines(true);
311                 }
312                 else
313                         rasty->SetLines(false);
314         }
315
316         ActivatGLMaterials(rasty);
317         ActivateTexGen(rasty);
318 }
319
320 void
321 KX_BlenderMaterial::ActivateMat( 
322         RAS_IRasterizer* rasty,  
323         TCachingInfo& cachingInfo
324         )const
325 {
326         KX_BlenderMaterial *tmp = const_cast<KX_BlenderMaterial*>(this);
327         if (GetCachingInfo() != cachingInfo) {
328                 if (!cachingInfo) 
329                         tmp->setTexData( false,rasty );
330                 
331                 cachingInfo = GetCachingInfo();
332
333                 if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) {
334                         tmp->setTexData( true,rasty  );
335                         rasty->EnableTextures(true);
336                 }
337                 else{
338                         tmp->setTexData( false,rasty);
339                         rasty->EnableTextures(false);
340                 }
341
342                 if(mMaterial->mode & RAS_IRasterizer::KX_TWOSIDE)
343                         rasty->SetCullFace(false);
344                 else
345                         rasty->SetCullFace(true);
346
347                 if (((mMaterial->ras_mode &WIRE)!=0) || mMaterial->mode & RAS_IRasterizer::KX_LINES)
348                 {               
349                         if((mMaterial->ras_mode &WIRE)!=0) 
350                                 rasty->SetCullFace(false);
351                         rasty->SetLines(true);
352                 }
353                 else
354                         rasty->SetLines(false);
355         }
356         ActivatGLMaterials(rasty);
357         ActivateTexGen(rasty);
358 }
359
360
361 bool 
362 KX_BlenderMaterial::Activate( 
363         RAS_IRasterizer* rasty,  
364         TCachingInfo& cachingInfo
365         )const
366 {
367         bool dopass = false;
368         if( RAS_EXT_support._ARB_shader_objects && ( mShader && mShader->Ok() ) ) {
369                 if( (mPass++) < mShader->getNumPass() ) {
370                         ActivatShaders(rasty, cachingInfo);
371                         dopass = true;
372                         return dopass;
373                 }
374                 else {
375                         mShader->SetProg(false);
376                         mPass = 0;
377                         dopass = false;
378                         return dopass;
379                 }
380         }
381         else {
382                 switch (mPass++)
383                 {
384                         case 0:
385                                 ActivateMat(rasty, cachingInfo);
386                                 dopass = true;
387                                 break;
388                         default:
389                                 mPass = 0;
390                                 dopass = false;
391                                 break;
392                 }
393         }
394         return dopass;
395 }
396
397 void KX_BlenderMaterial::ActivateMeshSlot(const KX_MeshSlot & ms, RAS_IRasterizer* rasty) const
398 {
399         if(mShader && RAS_EXT_support._ARB_shader_objects)
400                 mShader->Update(ms, rasty);
401 }
402
403 void KX_BlenderMaterial::ActivatGLMaterials( RAS_IRasterizer* rasty )const
404 {
405         rasty->SetSpecularity(
406                 mMaterial->speccolor[0]*mMaterial->spec_f,
407                 mMaterial->speccolor[1]*mMaterial->spec_f,
408                 mMaterial->speccolor[2]*mMaterial->spec_f,
409                 mMaterial->spec_f
410         );
411
412         rasty->SetShinyness( mMaterial->hard );
413
414         rasty->SetDiffuse(
415                 mMaterial->matcolor[0]*mMaterial->ref+mMaterial->emit, 
416                 mMaterial->matcolor[1]*mMaterial->ref+mMaterial->emit,
417                 mMaterial->matcolor[2]*mMaterial->ref+mMaterial->emit,
418                 1.0f);
419
420         rasty->SetEmissive(     
421                 mMaterial->matcolor[0]*mMaterial->emit,
422                 mMaterial->matcolor[1]*mMaterial->emit,
423                 mMaterial->matcolor[2]*mMaterial->emit,
424                 1.0 );
425
426         rasty->SetAmbient(mMaterial->amb);
427         if (mMaterial->material)
428                 rasty->SetPolygonOffset(-mMaterial->material->zoffs, 0.0);
429 }
430
431
432 void KX_BlenderMaterial::ActivateTexGen(RAS_IRasterizer *ras) const
433 {
434         if(mShader && RAS_EXT_support._ARB_shader_objects)
435                 if(mShader->GetAttribute() == BL_Shader::SHD_TANGENT)
436                         ras->SetAttrib(RAS_IRasterizer::RAS_TEXTANGENT);
437
438         for(int i=0; i<mMaterial->num_enabled; i++) {
439                 int mode = mMaterial->mapping[i].mapping;
440
441                 if (mode &USECUSTOMUV)
442                 {
443                         STR_String str = mMaterial->mapping[i].uvCoName;
444                         if (!str.IsEmpty())
445                                 ras->SetTexCoords(RAS_IRasterizer::RAS_TEXCO_UV2, i);
446                         continue;
447                 }
448
449                 if( mode &(USEREFL|USEOBJ))
450                         ras->SetTexCoords(RAS_IRasterizer::RAS_TEXCO_GEN, i);
451                 else if(mode &USEORCO)
452                         ras->SetTexCoords(RAS_IRasterizer::RAS_TEXCO_ORCO, i);
453                 else if(mode &USENORM)
454                         ras->SetTexCoords(RAS_IRasterizer::RAS_TEXCO_NORM, i);
455                 else if(mode &USEUV)
456                         ras->SetTexCoords(RAS_IRasterizer::RAS_TEXCO_UV1, i);
457                 else if(mode &USETANG)
458                         ras->SetTexCoords(RAS_IRasterizer::RAS_TEXTANGENT, i);
459                 else 
460                         ras->SetTexCoords(RAS_IRasterizer::RAS_TEXCO_DISABLE, i);
461         }
462 }
463
464 bool KX_BlenderMaterial::setDefaultBlending()
465 {
466         if( mMaterial->transp &TF_ADD) {
467                 glEnable(GL_BLEND);
468                 glBlendFunc(GL_ONE, GL_ONE);
469                 return true;
470         }
471         
472         if( mMaterial->transp & TF_ALPHA ) {
473                 glEnable(GL_BLEND);
474                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
475                 return true;
476         }
477         
478         glDisable(GL_BLEND);
479         return false;
480 }
481
482 void KX_BlenderMaterial::setTexMatrixData(int i)
483 {
484         glMatrixMode(GL_TEXTURE);
485         glLoadIdentity();
486
487 #ifdef GL_ARB_texture_cube_map
488         if( RAS_EXT_support._ARB_texture_cube_map && 
489                 mTextures[i].GetTextureType() == GL_TEXTURE_CUBE_MAP_ARB && 
490                 mMaterial->mapping[i].mapping & USEREFL) {
491                 glScalef( 
492                         mMaterial->mapping[i].scale[0], 
493                         -mMaterial->mapping[i].scale[1], 
494                         -mMaterial->mapping[i].scale[2]
495                 );
496         }
497         else
498 #endif
499         {
500                 glScalef( 
501                         mMaterial->mapping[i].scale[0], 
502                         mMaterial->mapping[i].scale[1], 
503                         mMaterial->mapping[i].scale[2]
504                 );
505         }
506         glTranslatef(
507                 mMaterial->mapping[i].offsets[0],
508                 mMaterial->mapping[i].offsets[1], 
509                 mMaterial->mapping[i].offsets[2]
510         );
511
512         glMatrixMode(GL_MODELVIEW);
513
514 }
515
516 static void GetProjPlane(BL_Material *mat, int index,int num, float*param)
517 {
518         param[0]=param[1]=param[2]=param[3]=0.f;
519         if( mat->mapping[index].projplane[num] == PROJX )
520                 param[0] = 1.f;
521         else if( mat->mapping[index].projplane[num] == PROJY )
522                 param[1] = 1.f;
523         else if( mat->mapping[index].projplane[num] == PROJZ)
524                 param[2] = 1.f;
525 }
526
527 void KX_BlenderMaterial::setObjectMatrixData(int i, RAS_IRasterizer *ras)
528 {
529         KX_GameObject *obj = 
530                 (KX_GameObject*)
531                 mScene->GetObjectList()->FindValue(mMaterial->mapping[i].objconame);
532
533         if(!obj) return;
534
535         glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
536         glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
537         glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
538
539         GLenum plane = GL_EYE_PLANE;
540
541         // figure plane gen
542         float proj[4]= {0.f,0.f,0.f,0.f};
543         GetProjPlane(mMaterial, i, 0, proj);
544         glTexGenfv(GL_S, plane, proj);
545         
546         GetProjPlane(mMaterial, i, 1, proj);
547         glTexGenfv(GL_T, plane, proj);
548
549         GetProjPlane(mMaterial, i, 2, proj);
550         glTexGenfv(GL_R, plane, proj);
551
552         glEnable(GL_TEXTURE_GEN_S);
553         glEnable(GL_TEXTURE_GEN_T);
554         glEnable(GL_TEXTURE_GEN_R);
555
556         MT_Matrix4x4 mvmat;
557         ras->GetViewMatrix(mvmat);
558
559         glMatrixMode(GL_TEXTURE);
560         glLoadIdentity();
561         glScalef( 
562                 mMaterial->mapping[i].scale[0], 
563                 mMaterial->mapping[i].scale[1], 
564                 mMaterial->mapping[i].scale[2]
565         );
566
567         MT_Point3 pos = obj->NodeGetWorldPosition();
568         MT_Vector4 matmul = MT_Vector4(pos[0], pos[1], pos[2], 1.f);
569         MT_Vector4 t = mvmat*matmul;
570
571         glTranslatef( (float)(-t[0]), (float)(-t[1]), (float)(-t[2]) );
572
573         glMatrixMode(GL_MODELVIEW);
574
575 }
576
577 // ------------------------------------
578 void KX_BlenderMaterial::UpdateIPO(
579         MT_Vector4 rgba,
580         MT_Vector3 specrgb,
581         MT_Scalar hard,
582         MT_Scalar spec,
583         MT_Scalar ref,
584         MT_Scalar emit,
585         MT_Scalar alpha
586         )
587 {
588         // only works one deep now
589         mMaterial->speccolor[0] = (float)(specrgb)[0];
590         mMaterial->speccolor[1] = (float)(specrgb)[1];
591         mMaterial->speccolor[2] = (float)(specrgb)[2];
592         mMaterial->matcolor[0]  = (float)(rgba[0]);
593         mMaterial->matcolor[1]  = (float)(rgba[1]);
594         mMaterial->matcolor[2]  = (float)(rgba[2]);
595         mMaterial->alpha                = (float)(alpha);
596         mMaterial->hard                 = (float)(hard);
597         mMaterial->emit                 = (float)(emit);
598         mMaterial->spec_f               = (float)(spec);
599 }
600
601
602 PyMethodDef KX_BlenderMaterial::Methods[] = 
603 {
604         KX_PYMETHODTABLE( KX_BlenderMaterial, getShader ),
605         KX_PYMETHODTABLE( KX_BlenderMaterial, getMaterialIndex ),
606         KX_PYMETHODTABLE( KX_BlenderMaterial, setBlending ),
607         {NULL,NULL} //Sentinel
608 };
609
610
611 PyTypeObject KX_BlenderMaterial::Type = {
612         PyObject_HEAD_INIT(&PyType_Type)
613                 0,
614                 "KX_BlenderMaterial",
615                 sizeof(KX_BlenderMaterial),
616                 0,
617                 PyDestructor,
618                 0,
619                 __getattr,
620                 __setattr,
621                 0,
622                 __repr,
623                 0
624 };
625
626
627 PyParentObject KX_BlenderMaterial::Parents[] = {
628         &PyObjectPlus::Type,
629         &KX_BlenderMaterial::Type,
630         NULL
631 };
632
633
634 PyObject* KX_BlenderMaterial::_getattr(const STR_String& attr)
635 {
636         _getattr_up(PyObjectPlus);
637 }
638
639 int KX_BlenderMaterial::_setattr(const STR_String& attr, PyObject *pyvalue)
640 {
641         return PyObjectPlus::_setattr(attr, pyvalue);
642 }
643
644
645 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()")
646 {
647 #ifdef GL_ARB_fragment_shader
648         if( !RAS_EXT_support._ARB_fragment_shader) {
649                 if(!mModified)
650                         spit("Fragment shaders not supported");
651         
652                 mModified = true;
653                 Py_Return;
654         }
655 #endif
656
657 #ifdef GL_ARB_vertex_shader
658         if( !RAS_EXT_support._ARB_vertex_shader) {
659                 if(!mModified)
660                         spit("Vertex shaders not supported");
661
662                 mModified = true;
663                 Py_Return;
664         }
665 #endif
666
667 #ifdef GL_ARB_shader_objects
668         if(!RAS_EXT_support._ARB_shader_objects)  {
669                 if(!mModified)
670                         spit("GLSL not supported");
671                 mModified = true;
672                 Py_Return;
673         }
674         else {
675                 // returns Py_None on error
676                 // the calling script will need to check
677
678                 if(!mShader && !mModified) {
679                         mShader = new BL_Shader();
680                         mModified = true;
681                 }
682
683                 if(mShader && !mShader->GetError()) {
684                         mMaterial->SetSharedMaterial(true);
685                         Py_INCREF(mShader);
686                         return mShader;
687                 }else
688                 {
689                         // decref all references to the object
690                         // then delete it!
691                         // We will then go back to fixed functionality
692                         // for this material
693                         if(mShader) {
694                                 if(mShader->ob_refcnt > 1) {
695                                         Py_DECREF(mShader);
696                                 }
697                                 else {
698                                         delete mShader;
699                                         mShader=0;
700                                 }
701                         }
702                 }
703                 Py_Return;
704         }
705         PyErr_Format(PyExc_ValueError, "GLSL Error");
706         return NULL;
707
708 #else
709         Py_Return;
710 #endif//GL_ARB_shader_objects
711 }
712
713
714 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getMaterialIndex, "getMaterialIndex()")
715 {
716         return PyInt_FromLong( mMaterial->material_index );
717 }
718
719 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getTexture, "getTexture( index )" )
720 {
721         // TODO: enable python switching
722         return NULL;
723 }
724
725 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, setTexture , "setTexture( index, tex)")
726 {
727         // TODO: enable python switching
728         return NULL;
729 }
730
731 static unsigned int GL_array[11] = {
732         GL_ZERO,
733         GL_ONE,
734         GL_SRC_COLOR,
735         GL_ONE_MINUS_SRC_COLOR,
736         GL_DST_COLOR,
737         GL_ONE_MINUS_DST_COLOR,
738         GL_SRC_ALPHA,
739         GL_ONE_MINUS_SRC_ALPHA,
740         GL_DST_ALPHA,
741         GL_ONE_MINUS_DST_ALPHA,
742         GL_SRC_ALPHA_SATURATE
743 };
744
745 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, setBlending , "setBlending( GameLogic.src, GameLogic.dest)")
746 {
747         unsigned int b[2];
748         if(PyArg_ParseTuple(args, "ii", &b[0], &b[1]))
749         {
750                 bool value_found[2] = {false, false};
751                 for(int i=0; i<11; i++)
752                 {
753                         if(b[0] == GL_array[i]) {
754                                 value_found[0] = true;
755                                 mBlendFunc[0] = b[0];
756                         }
757                         if(b[1] == GL_array[i]) {
758                                 value_found[1] = true;
759                                 mBlendFunc[1] = b[1];
760                         }
761                         if(value_found[0] && value_found[1]) break;
762                 }
763                 if(!value_found[0] || !value_found[1]) {
764                         PyErr_Format(PyExc_ValueError, "invalid enum.");
765                         return NULL;
766                 }
767                 mUserDefBlend = true;
768                 Py_Return;
769         }
770         return NULL;
771 }
772