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