BGE: Allow access to original texture openGL Bind code/Id/Number
[blender.git] / source / gameengine / Ketsji / KX_BlenderMaterial.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * ***** END GPL LICENSE BLOCK *****
19  */
20
21 /** \file gameengine/Ketsji/KX_BlenderMaterial.cpp
22  *  \ingroup ketsji
23  */
24
25 #include "glew-mx.h"
26
27 #include "KX_BlenderMaterial.h"
28 #include "BL_Material.h"
29 #include "KX_Scene.h"
30 #include "KX_Light.h"
31 #include "KX_GameObject.h"
32 #include "KX_MeshProxy.h"
33 #include "KX_PyMath.h"
34
35 #include "MT_Vector3.h"
36 #include "MT_Vector4.h"
37 #include "MT_Matrix4x4.h"
38
39 #include "RAS_BucketManager.h"
40 #include "RAS_MeshObject.h"
41 #include "RAS_IRasterizer.h"
42
43 #include "GPU_draw.h"
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 #include "BLI_utildefines.h"
55 #include "BLI_math.h"
56
57 #define spit(x) std::cout << x << std::endl;
58
59 BL_Shader *KX_BlenderMaterial::mLastShader = NULL;
60 BL_BlenderShader *KX_BlenderMaterial::mLastBlenderShader = NULL;
61
62 //static PyObject *gTextureDict = 0;
63
64 KX_BlenderMaterial::KX_BlenderMaterial()
65 :       PyObjectPlus(),
66         RAS_IPolyMaterial(),
67         mMaterial(NULL),
68         mShader(0),
69         mBlenderShader(0),
70         mScene(NULL),
71         mUserDefBlend(0),
72         mModified(0),
73         mConstructed(false),
74         mPass(0)
75 {
76 }
77
78 void KX_BlenderMaterial::Initialize(
79         KX_Scene *scene,
80         BL_Material *data,
81         GameSettings *game,
82         int lightlayer)
83 {
84         RAS_IPolyMaterial::Initialize(
85                 data->texname[0],
86                 data->matname,
87                 data->materialindex,
88                 data->tile,
89                 data->tilexrep[0],
90                 data->tileyrep[0],
91                 data->alphablend,
92                 ((data->ras_mode &ALPHA)!=0),
93                 ((data->ras_mode &ZSORT)!=0),
94                 ((data->ras_mode &USE_LIGHT)!=0),
95                 ((data->ras_mode &TEX)),
96                 game
97         );
98         Material *ma = data->material;
99
100         // Save material data to restore on exit
101         mSavedData.r = ma->r;
102         mSavedData.g = ma->g;
103         mSavedData.b = ma->b;
104         mSavedData.a = ma->alpha;
105         mSavedData.specr = ma->specr;
106         mSavedData.specg = ma->specg;
107         mSavedData.specb = ma->specb;
108         mSavedData.spec = ma->spec;
109         mSavedData.ref = ma->ref;
110         mSavedData.hardness = ma->har;
111         mSavedData.emit = ma->emit;
112
113         mMaterial = data;
114         mShader = 0;
115         mBlenderShader = 0;
116         mScene = scene;
117         mUserDefBlend = 0;
118         mModified = 0;
119         mConstructed = false;
120         mPass = 0;
121         mLightLayer = lightlayer;
122         // --------------------------------
123         // RAS_IPolyMaterial variables...
124         m_flag |= RAS_BLENDERMAT;
125         m_flag |= (mMaterial->IdMode>=ONETEX)? RAS_MULTITEX: 0;
126         m_flag |= ((mMaterial->ras_mode & USE_LIGHT)!=0)? RAS_MULTILIGHT: 0;
127         m_flag |= (mMaterial->glslmat)? RAS_BLENDERGLSL: 0;
128         m_flag |= ((mMaterial->ras_mode & CAST_SHADOW)!=0)? RAS_CASTSHADOW: 0;
129         m_flag |= ((mMaterial->ras_mode & ONLY_SHADOW)!=0)? RAS_ONLYSHADOW: 0;
130
131         // test the sum of the various modes for equality
132         // so we can ether accept or reject this material
133         // as being equal, this is rather important to
134         // prevent material bleeding
135         for (int i=0; i<BL_Texture::GetMaxUnits(); i++) {
136                 m_multimode     += (mMaterial->flag[i] + mMaterial->blend_mode[i]);
137         }
138         m_multimode += mMaterial->IdMode+ (mMaterial->ras_mode & ~(USE_LIGHT));
139 }
140
141 KX_BlenderMaterial::~KX_BlenderMaterial()
142 {
143         Material *ma = mMaterial->material;
144         // Restore Blender material data
145         ma->r = mSavedData.r;
146         ma->g = mSavedData.g;
147         ma->b = mSavedData.b;
148         ma->alpha = mSavedData.a;
149         ma->specr = mSavedData.specr;
150         ma->specg = mSavedData.specg;
151         ma->specb = mSavedData.specb;
152         ma->spec = mSavedData.spec;
153         ma->ref = mSavedData.ref;
154         ma->har = mSavedData.hardness;
155         ma->emit = mSavedData.emit;
156
157         // cleanup work
158         if (mConstructed)
159                 // clean only if material was actually used
160                 OnExit();
161 }
162
163 MTexPoly *KX_BlenderMaterial::GetMTexPoly() const
164 {
165         // fonts on polys
166         return &mMaterial->mtexpoly;
167 }
168
169 unsigned int* KX_BlenderMaterial::GetMCol() const
170 {
171         // fonts on polys
172         return mMaterial->rgb;
173 }
174
175 void KX_BlenderMaterial::GetMaterialRGBAColor(unsigned char *rgba) const
176 {
177         if (mMaterial) {
178                 *rgba++ = (unsigned char)(mMaterial->matcolor[0] * 255.0f);
179                 *rgba++ = (unsigned char)(mMaterial->matcolor[1] * 255.0f);
180                 *rgba++ = (unsigned char)(mMaterial->matcolor[2] * 255.0f);
181                 *rgba++ = (unsigned char)(mMaterial->matcolor[3] * 255.0f);
182         } else
183                 RAS_IPolyMaterial::GetMaterialRGBAColor(rgba);
184 }
185
186 Material *KX_BlenderMaterial::GetBlenderMaterial() const
187 {
188         return mMaterial->material;
189 }
190
191 Image *KX_BlenderMaterial::GetBlenderImage() const
192 {
193         return mMaterial->mtexpoly.tpage;
194 }
195
196 Scene* KX_BlenderMaterial::GetBlenderScene() const
197 {
198         return mScene->GetBlenderScene();
199 }
200
201 void KX_BlenderMaterial::ReleaseMaterial()
202 {
203         if (mBlenderShader)
204                 mBlenderShader->ReloadMaterial();
205 }
206
207 void KX_BlenderMaterial::InitTextures()
208 {
209         // for each unique material...
210         int i;
211         for (i=0; i<BL_Texture::GetMaxUnits(); i++) {
212                 if ( mMaterial->mapping[i].mapping & USEENV ) {
213                         if (!GLEW_ARB_texture_cube_map) {
214                                 spit("CubeMap textures not supported");
215                                 continue;
216                         }
217                         if (!mTextures[i].InitCubeMap(i, mMaterial->cubemap[i] ) )
218                                 spit("unable to initialize image("<<i<<") in "<<
219                                      mMaterial->matname<< ", image will not be available");
220                 }
221                 /* If we're using glsl materials, the textures are handled by bf_gpu, so don't load them twice!
222                  * However, if we're using a custom shader, then we still need to load the textures ourselves. */
223                 else if (!mMaterial->glslmat || mShader) {
224                         if ( mMaterial->img[i] ) {
225                                 if ( ! mTextures[i].InitFromImage(i, mMaterial->img[i], (mMaterial->flag[i] &MIPMAP)!=0 ))
226                                         spit("unable to initialize image("<<i<<") in "<< 
227                                                 mMaterial->matname<< ", image will not be available");
228                         }
229                 }
230         }
231 }
232
233 void KX_BlenderMaterial::OnConstruction()
234 {
235         if (mConstructed)
236                 // when material are reused between objects
237                 return;
238         
239         if (mMaterial->glslmat)
240                 SetBlenderGLSLShader();
241
242         InitTextures();
243
244         mBlendFunc[0] =0;
245         mBlendFunc[1] =0;
246         mConstructed = true;
247 }
248
249 void KX_BlenderMaterial::EndFrame()
250 {
251         if (mLastBlenderShader) {
252                 mLastBlenderShader->SetProg(false);
253                 mLastBlenderShader = NULL;
254         }
255
256         if (mLastShader) {
257                 mLastShader->SetProg(false);
258                 mLastShader = NULL;
259         }
260 }
261
262 void KX_BlenderMaterial::OnExit()
263 {
264         if ( mShader ) {
265                 //note, the shader here is allocated, per unique material
266                 //and this function is called per face
267                 if (mShader == mLastShader) {
268                         mShader->SetProg(false);
269                         mLastShader = NULL;
270                 }
271
272                 delete mShader;
273                 mShader = 0;
274         }
275
276         if ( mBlenderShader ) {
277                 if (mBlenderShader == mLastBlenderShader) {
278                         mBlenderShader->SetProg(false);
279                         mLastBlenderShader = NULL;
280                 }
281
282                 delete mBlenderShader;
283                 mBlenderShader = 0;
284         }
285
286         BL_Texture::ActivateFirst();
287         for (int i=0; i<BL_Texture::GetMaxUnits(); i++) {
288                 if (!mTextures[i].Ok()) continue;
289                 BL_Texture::ActivateUnit(i);
290                 mTextures[i].DeleteTex();
291                 mTextures[i].DisableUnit();
292         }
293
294         /* used to call with 'mMaterial->tface' but this can be a freed array,
295          * see: [#30493], so just call with NULL, this is best since it clears
296          * the 'lastface' pointer in GPU too - campbell */
297         GPU_set_tpage(NULL, 1, mMaterial->alphablend);
298 }
299
300
301 void KX_BlenderMaterial::setShaderData( bool enable, RAS_IRasterizer *ras)
302 {
303         MT_assert(GLEW_ARB_shader_objects && mShader);
304
305         int i;
306         if ( !enable || !mShader->Ok() ) {
307                 // frame cleanup.
308                 if (mShader == mLastShader) {
309                         mShader->SetProg(false);
310                         mLastShader = NULL;
311                 }
312
313                 ras->SetAlphaBlend(TF_SOLID);
314                 BL_Texture::DisableAllTextures();
315                 return;
316         }
317
318         BL_Texture::DisableAllTextures();
319         mShader->SetProg(true);
320         mLastShader = mShader;
321         
322         BL_Texture::ActivateFirst();
323
324         mShader->ApplyShader();
325
326         // for each enabled unit
327         for (i=0; i<BL_Texture::GetMaxUnits(); i++) {
328                 if (!mTextures[i].Ok()) continue;
329                 mTextures[i].ActivateTexture();
330                 mTextures[0].SetMapping(mMaterial->mapping[i].mapping);
331         }
332
333         if (!mUserDefBlend) {
334                 ras->SetAlphaBlend(mMaterial->alphablend);
335         }
336         else {
337                 ras->SetAlphaBlend(TF_SOLID);
338                 ras->SetAlphaBlend(-1); // indicates custom mode
339
340                 // tested to be valid enums
341                 glEnable(GL_BLEND);
342                 glBlendFunc(mBlendFunc[0], mBlendFunc[1]);
343         }
344 }
345
346 void KX_BlenderMaterial::setBlenderShaderData( bool enable, RAS_IRasterizer *ras)
347 {
348         if ( !enable || !mBlenderShader->Ok() ) {
349                 ras->SetAlphaBlend(TF_SOLID);
350
351                 // frame cleanup.
352                 if (mLastBlenderShader) {
353                         mLastBlenderShader->SetProg(false);
354                         mLastBlenderShader= NULL;
355                 }
356                 else
357                         BL_Texture::DisableAllTextures();
358
359                 return;
360         }
361
362         if (!mBlenderShader->Equals(mLastBlenderShader)) {
363                 ras->SetAlphaBlend(mMaterial->alphablend);
364
365                 if (mLastBlenderShader)
366                         mLastBlenderShader->SetProg(false);
367                 else
368                         BL_Texture::DisableAllTextures();
369
370                 mBlenderShader->SetProg(true, ras->GetTime(), ras);
371                 mLastBlenderShader= mBlenderShader;
372         }
373 }
374
375 void KX_BlenderMaterial::setTexData( bool enable, RAS_IRasterizer *ras)
376 {
377         BL_Texture::DisableAllTextures();
378
379         if ( !enable ) {
380                 ras->SetAlphaBlend(TF_SOLID);
381                 return;
382         }
383
384         BL_Texture::ActivateFirst();
385
386         if ( mMaterial->IdMode == DEFAULT_BLENDER ) {
387                 ras->SetAlphaBlend(mMaterial->alphablend);
388                 return;
389         }
390
391         if ( mMaterial->IdMode == TEXFACE ) {
392                 // no material connected to the object
393                 if ( mTextures[0].Ok() ) {
394                         mTextures[0].ActivateTexture();
395                         mTextures[0].setTexEnv(0, true);
396                         mTextures[0].SetMapping(mMaterial->mapping[0].mapping);
397                         ras->SetAlphaBlend(mMaterial->alphablend);
398                 }
399                 return;
400         }
401
402         int mode = 0,i=0;
403         for (i=0; i<BL_Texture::GetMaxUnits(); i++) {
404                 if ( !mTextures[i].Ok() ) continue;
405
406                 mTextures[i].ActivateTexture();
407                 mTextures[i].setTexEnv(mMaterial);
408                 mode = mMaterial->mapping[i].mapping;
409
410                 if (mode &USEOBJ)
411                         setObjectMatrixData(i, ras);
412                 else
413                         mTextures[i].SetMapping(mode);
414                 
415                 if (!(mode &USEOBJ))
416                         setTexMatrixData( i );
417         }
418
419         if (!mUserDefBlend) {
420                 ras->SetAlphaBlend(mMaterial->alphablend);
421         }
422         else {
423                 ras->SetAlphaBlend(TF_SOLID);
424                 ras->SetAlphaBlend(-1); // indicates custom mode
425
426                 glEnable(GL_BLEND);
427                 glBlendFunc(mBlendFunc[0], mBlendFunc[1]);
428         }
429 }
430
431 void
432 KX_BlenderMaterial::ActivatShaders(
433         RAS_IRasterizer* rasty, 
434         TCachingInfo& cachingInfo)const
435 {
436         KX_BlenderMaterial *tmp = const_cast<KX_BlenderMaterial*>(this);
437
438         // reset... 
439         if (tmp->mMaterial->IsShared()) 
440                 cachingInfo =0;
441
442         if (mLastBlenderShader) {
443                 mLastBlenderShader->SetProg(false);
444                 mLastBlenderShader= NULL;
445         }
446
447         if (GetCachingInfo() != cachingInfo) {
448
449                 if (!cachingInfo)
450                         tmp->setShaderData(false, rasty);
451                 
452                 cachingInfo = GetCachingInfo();
453         
454                 if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED)
455                         tmp->setShaderData(true, rasty);
456                 else if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_SHADOW && mMaterial->alphablend != GEMAT_SOLID && !rasty->GetUsingOverrideShader())
457                         tmp->setShaderData(true, rasty);
458                 else
459                         tmp->setShaderData(false, rasty);
460
461                 if (mMaterial->ras_mode &TWOSIDED)
462                         rasty->SetCullFace(false);
463                 else
464                         rasty->SetCullFace(true);
465
466                 if ((mMaterial->ras_mode &WIRE) ||
467                     (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME))
468                 {
469                         if (mMaterial->ras_mode &WIRE) 
470                                 rasty->SetCullFace(false);
471                         rasty->SetLines(true);
472                 }
473                 else
474                         rasty->SetLines(false);
475                 ActivatGLMaterials(rasty);
476                 ActivateTexGen(rasty);
477         }
478
479         //ActivatGLMaterials(rasty);
480         //ActivateTexGen(rasty);
481 }
482
483 void
484 KX_BlenderMaterial::ActivateBlenderShaders(
485         RAS_IRasterizer* rasty, 
486         TCachingInfo& cachingInfo)const
487 {
488         KX_BlenderMaterial *tmp = const_cast<KX_BlenderMaterial*>(this);
489
490         if (mLastShader) {
491                 mLastShader->SetProg(false);
492                 mLastShader= NULL;
493         }
494
495         if (GetCachingInfo() != cachingInfo) {
496                 if (!cachingInfo)
497                         tmp->setBlenderShaderData(false, rasty);
498                 
499                 cachingInfo = GetCachingInfo();
500         
501                 if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED)
502                         tmp->setBlenderShaderData(true, rasty);
503                 else if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_SHADOW && mMaterial->alphablend != GEMAT_SOLID && !rasty->GetUsingOverrideShader())
504                         tmp->setBlenderShaderData(true, rasty);
505                 else
506                         tmp->setBlenderShaderData(false, rasty);
507
508                 if (mMaterial->ras_mode &TWOSIDED)
509                         rasty->SetCullFace(false);
510                 else
511                         rasty->SetCullFace(true);
512
513                 if ((mMaterial->ras_mode &WIRE) ||
514                     (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME))
515                 {
516                         if (mMaterial->ras_mode &WIRE) 
517                                 rasty->SetCullFace(false);
518                         rasty->SetLines(true);
519                 }
520                 else
521                         rasty->SetLines(false);
522
523                 ActivatGLMaterials(rasty);
524                 mBlenderShader->SetAttribs(rasty, mMaterial);
525         }
526 }
527
528 void
529 KX_BlenderMaterial::ActivateMat( 
530         RAS_IRasterizer* rasty,  
531         TCachingInfo& cachingInfo
532         )const
533 {
534         KX_BlenderMaterial *tmp = const_cast<KX_BlenderMaterial*>(this);
535
536         if (mLastShader) {
537                 mLastShader->SetProg(false);
538                 mLastShader= NULL;
539         }
540
541         if (mLastBlenderShader) {
542                 mLastBlenderShader->SetProg(false);
543                 mLastBlenderShader= NULL;
544         }
545
546         if (GetCachingInfo() != cachingInfo) {
547                 if (!cachingInfo) 
548                         tmp->setTexData( false,rasty );
549                 
550                 cachingInfo = GetCachingInfo();
551
552                 if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED)
553                         tmp->setTexData( true,rasty  );
554                 else if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_SHADOW && mMaterial->alphablend != GEMAT_SOLID && !rasty->GetUsingOverrideShader())
555                         tmp->setTexData(true, rasty);
556                 else
557                         tmp->setTexData( false,rasty);
558
559                 if (mMaterial->ras_mode &TWOSIDED)
560                         rasty->SetCullFace(false);
561                 else
562                         rasty->SetCullFace(true);
563
564                 if ((mMaterial->ras_mode &WIRE) ||
565                     (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME))
566                 {
567                         if (mMaterial->ras_mode &WIRE) 
568                                 rasty->SetCullFace(false);
569                         rasty->SetLines(true);
570                 }
571                 else
572                         rasty->SetLines(false);
573                 ActivatGLMaterials(rasty);
574                 ActivateTexGen(rasty);
575         }
576
577         //ActivatGLMaterials(rasty);
578         //ActivateTexGen(rasty);
579 }
580
581 bool 
582 KX_BlenderMaterial::Activate( 
583         RAS_IRasterizer* rasty,  
584         TCachingInfo& cachingInfo
585         )const
586 {
587         if (GLEW_ARB_shader_objects && (mShader && mShader->Ok())) {
588                 if ((mPass++) < mShader->getNumPass() ) {
589                         ActivatShaders(rasty, cachingInfo);
590                         return true;
591                 }
592                 else {
593                         if (mShader == mLastShader) {
594                                 mShader->SetProg(false);
595                                 mLastShader = NULL;
596                         }
597                         mPass = 0;
598                         return false;
599                 }
600         }
601         else if ( GLEW_ARB_shader_objects && (mBlenderShader && mBlenderShader->Ok() ) ) {
602                 if (mPass++ == 0) {
603                         ActivateBlenderShaders(rasty, cachingInfo);
604                         return true;
605                 }
606                 else {
607                         mPass = 0;
608                         return false;
609                 }
610         }
611         else {
612                 if (mPass++ == 0) {
613                         ActivateMat(rasty, cachingInfo);
614                         return true;
615                 }
616                 else {
617                         mPass = 0;
618                         return false;
619                 }
620         }
621 }
622
623 bool KX_BlenderMaterial::UsesLighting(RAS_IRasterizer *rasty) const
624 {
625         if (!RAS_IPolyMaterial::UsesLighting(rasty))
626                 return false;
627
628         if (mShader && mShader->Ok())
629                 return true;
630         else if (mBlenderShader && mBlenderShader->Ok())
631                 return false;
632         else
633                 return true;
634 }
635
636 void KX_BlenderMaterial::ActivateMeshSlot(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty) const
637 {
638         if (mShader && GLEW_ARB_shader_objects) {
639                 mShader->Update(ms, rasty);
640         }
641         else if (mBlenderShader && GLEW_ARB_shader_objects) {
642                 int alphablend;
643
644                 mBlenderShader->Update(ms, rasty);
645
646                 /* we do blend modes here, because they can change per object
647                  * with the same material due to obcolor/obalpha */
648                 alphablend = mBlenderShader->GetAlphaBlend();
649                 if (ELEM(alphablend, GEMAT_SOLID, GEMAT_ALPHA, GEMAT_ALPHA_SORT) && mMaterial->alphablend != GEMAT_SOLID)
650                         alphablend = mMaterial->alphablend;
651
652                 rasty->SetAlphaBlend(alphablend);
653         }
654 }
655
656 void KX_BlenderMaterial::ActivatGLMaterials( RAS_IRasterizer* rasty )const
657 {
658         if (mShader || !mBlenderShader) {
659                 rasty->SetSpecularity(
660                         mMaterial->speccolor[0]*mMaterial->spec_f,
661                         mMaterial->speccolor[1]*mMaterial->spec_f,
662                         mMaterial->speccolor[2]*mMaterial->spec_f,
663                         mMaterial->spec_f
664                 );
665
666                 rasty->SetShinyness( mMaterial->hard );
667
668                 rasty->SetDiffuse(
669                         mMaterial->matcolor[0]*mMaterial->ref+mMaterial->emit, 
670                         mMaterial->matcolor[1]*mMaterial->ref+mMaterial->emit,
671                         mMaterial->matcolor[2]*mMaterial->ref+mMaterial->emit,
672                         1.0f);
673
674                 rasty->SetEmissive(
675                         mMaterial->matcolor[0]*mMaterial->emit,
676                         mMaterial->matcolor[1]*mMaterial->emit,
677                         mMaterial->matcolor[2]*mMaterial->emit,
678                         1.0f );
679
680                 rasty->SetAmbient(mMaterial->amb);
681         }
682
683         if (mMaterial->material)
684                 rasty->SetPolygonOffset(-mMaterial->material->zoffs, 0.0f);
685 }
686
687
688 void KX_BlenderMaterial::ActivateTexGen(RAS_IRasterizer *ras) const
689 {
690         if (ras->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED || 
691                 (ras->GetDrawingMode() == RAS_IRasterizer::KX_SHADOW && mMaterial->alphablend != GEMAT_SOLID && !ras->GetUsingOverrideShader())) {
692                 ras->SetAttribNum(0);
693                 if (mShader && GLEW_ARB_shader_objects) {
694                         if (mShader->GetAttribute() == BL_Shader::SHD_TANGENT) {
695                                 ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_DISABLE, 0);
696                                 ras->SetAttrib(RAS_IRasterizer::RAS_TEXTANGENT, 1);
697                                 ras->SetAttribNum(2);
698                         }
699                 }
700
701                 ras->SetTexCoordNum(mMaterial->num_enabled);
702
703                 for (int i=0; i<BL_Texture::GetMaxUnits(); i++) {
704                         int mode = mMaterial->mapping[i].mapping;
705
706                         if ( mode &(USEREFL|USEOBJ))
707                                 ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_GEN, i);
708                         else if (mode &USEORCO)
709                                 ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_ORCO, i);
710                         else if (mode &USENORM)
711                                 ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_NORM, i);
712                         else if (mode &USEUV)
713                                 ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_UV, i);
714                         else if (mode &USETANG)
715                                 ras->SetTexCoord(RAS_IRasterizer::RAS_TEXTANGENT, i);
716                         else 
717                                 ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_DISABLE, i);
718                 }
719         }
720 }
721
722 void KX_BlenderMaterial::setTexMatrixData(int i)
723 {
724         glMatrixMode(GL_TEXTURE);
725         glLoadIdentity();
726
727         if ( GLEW_ARB_texture_cube_map && 
728                 mTextures[i].GetTextureType() == GL_TEXTURE_CUBE_MAP_ARB && 
729                 mMaterial->mapping[i].mapping & USEREFL) {
730                 glScalef( 
731                         mMaterial->mapping[i].scale[0], 
732                         -mMaterial->mapping[i].scale[1], 
733                         -mMaterial->mapping[i].scale[2]
734                 );
735         }
736         else
737         {
738                 glScalef( 
739                         mMaterial->mapping[i].scale[0], 
740                         mMaterial->mapping[i].scale[1], 
741                         mMaterial->mapping[i].scale[2]
742                 );
743         }
744         glTranslatef(
745                 mMaterial->mapping[i].offsets[0],
746                 mMaterial->mapping[i].offsets[1], 
747                 mMaterial->mapping[i].offsets[2]
748         );
749
750         glMatrixMode(GL_MODELVIEW);
751
752 }
753
754 static void GetProjPlane(BL_Material *mat, int index,int num, float*param)
755 {
756         param[0]=param[1]=param[2]=param[3]=0.f;
757         if ( mat->mapping[index].projplane[num] == PROJX )
758                 param[0] = 1.f;
759         else if ( mat->mapping[index].projplane[num] == PROJY )
760                 param[1] = 1.f;
761         else if ( mat->mapping[index].projplane[num] == PROJZ)
762                 param[2] = 1.f;
763 }
764
765 void KX_BlenderMaterial::setObjectMatrixData(int i, RAS_IRasterizer *ras)
766 {
767         KX_GameObject *obj = 
768                 (KX_GameObject*)
769                 mScene->GetObjectList()->FindValue(mMaterial->mapping[i].objconame);
770
771         if (!obj) return;
772
773         glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
774         glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
775         glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
776
777         GLenum plane = GL_EYE_PLANE;
778
779         // figure plane gen
780         float proj[4] = {0.f,0.f,0.f,0.f};
781         GetProjPlane(mMaterial, i, 0, proj);
782         glTexGenfv(GL_S, plane, proj);
783         
784         GetProjPlane(mMaterial, i, 1, proj);
785         glTexGenfv(GL_T, plane, proj);
786
787         GetProjPlane(mMaterial, i, 2, proj);
788         glTexGenfv(GL_R, plane, proj);
789
790         glEnable(GL_TEXTURE_GEN_S);
791         glEnable(GL_TEXTURE_GEN_T);
792         glEnable(GL_TEXTURE_GEN_R);
793
794         const MT_Matrix4x4& mvmat = ras->GetViewMatrix();
795
796         glMatrixMode(GL_TEXTURE);
797         glLoadIdentity();
798         glScalef( 
799                 mMaterial->mapping[i].scale[0], 
800                 mMaterial->mapping[i].scale[1], 
801                 mMaterial->mapping[i].scale[2]
802         );
803
804         MT_Point3 pos = obj->NodeGetWorldPosition();
805         MT_Vector4 matmul = MT_Vector4(pos[0], pos[1], pos[2], 1.f);
806         MT_Vector4 t = mvmat*matmul;
807
808         glTranslatef( (float)(-t[0]), (float)(-t[1]), (float)(-t[2]) );
809
810         glMatrixMode(GL_MODELVIEW);
811
812 }
813
814 // ------------------------------------
815 void KX_BlenderMaterial::UpdateIPO(
816         MT_Vector4 rgba,
817         MT_Vector3 specrgb,
818         MT_Scalar hard,
819         MT_Scalar spec,
820         MT_Scalar ref,
821         MT_Scalar emit,
822         MT_Scalar alpha
823         )
824 {
825         // only works one deep now
826
827         // GLSL                                                 Multitexture                            Input
828         mMaterial->material->specr      = mMaterial->speccolor[0]       = (float)(specrgb)[0];
829         mMaterial->material->specg      = mMaterial->speccolor[1]       = (float)(specrgb)[1];
830         mMaterial->material->specb      = mMaterial->speccolor[2]       = (float)(specrgb)[2];
831         mMaterial->material->r          = mMaterial->matcolor[0]        = (float)(rgba[0]);
832         mMaterial->material->g          = mMaterial->matcolor[1]        = (float)(rgba[1]);
833         mMaterial->material->b          = mMaterial->matcolor[2]        = (float)(rgba[2]);
834         mMaterial->material->alpha      = mMaterial->alpha                      = (float)(rgba[3]);
835         mMaterial->material->har        = mMaterial->hard                       = (float)(hard);
836         mMaterial->material->emit       = mMaterial->emit                       = (float)(emit);
837         mMaterial->material->spec       = mMaterial->spec_f                     = (float)(spec);
838         mMaterial->material->ref        = mMaterial->ref                        = (float)(ref);
839 }
840
841 void KX_BlenderMaterial::Replace_IScene(SCA_IScene *val)
842 {
843         mScene= static_cast<KX_Scene *>(val);
844
845         OnConstruction();
846 }
847
848 BL_Material *KX_BlenderMaterial::GetBLMaterial()
849 {
850         return mMaterial;
851 }
852
853 void KX_BlenderMaterial::SetBlenderGLSLShader()
854 {
855         if (!mBlenderShader)
856                 mBlenderShader = new BL_BlenderShader(mScene, mMaterial->material, mLightLayer);
857
858         if (!mBlenderShader->Ok()) {
859                 delete mBlenderShader;
860                 mBlenderShader = 0;
861         }
862 }
863
864 #ifdef USE_MATHUTILS
865
866 #define MATHUTILS_COL_CB_MATERIAL_SPECULAR_COLOR 1
867 #define MATHUTILS_COL_CB_MATERIAL_DIFFUSE_COLOR 2
868
869 static unsigned char mathutils_kxblendermaterial_color_cb_index = -1; /* index for our callbacks */
870
871 static int mathutils_kxblendermaterial_generic_check(BaseMathObject *bmo)
872 {
873         KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>BGE_PROXY_REF(bmo->cb_user);
874         if (!self)
875                 return -1;
876
877         return 0;
878 }
879
880 static int mathutils_kxblendermaterial_color_get(BaseMathObject *bmo, int subtype)
881 {
882         KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial*>BGE_PROXY_REF(bmo->cb_user);
883         if (!self)
884                 return -1;
885
886         switch (subtype) {
887                 case MATHUTILS_COL_CB_MATERIAL_DIFFUSE_COLOR:
888                 {
889                         copy_v3_v3(bmo->data, self->GetBLMaterial()->matcolor);
890                         break;
891                 }
892                 case MATHUTILS_COL_CB_MATERIAL_SPECULAR_COLOR:
893                 {
894                         copy_v3_v3(bmo->data, self->GetBLMaterial()->speccolor);
895                         break;
896                 }
897         }
898
899         return 0;
900 }
901
902 static int mathutils_kxblendermaterial_color_set(BaseMathObject *bmo, int subtype)
903 {
904         KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>BGE_PROXY_REF(bmo->cb_user);
905         if (!self)
906                 return -1;
907
908         switch (subtype) {
909                 case MATHUTILS_COL_CB_MATERIAL_DIFFUSE_COLOR:
910                 {
911                         BL_Material *mat = self->GetBLMaterial();
912                         copy_v3_v3(mat->matcolor, bmo->data);
913                         mat->material->r = bmo->data[0];
914                         mat->material->g = bmo->data[1];
915                         mat->material->b = bmo->data[2];
916                         break;
917                 }
918                 case MATHUTILS_COL_CB_MATERIAL_SPECULAR_COLOR:
919                 {
920                         BL_Material *mat = self->GetBLMaterial();
921                         copy_v3_v3(mat->speccolor, bmo->data);
922                         mat->material->specr = bmo->data[0];
923                         mat->material->specg = bmo->data[1];
924                         mat->material->specb = bmo->data[2];
925                         break;
926                 }
927         }
928
929         return 0;
930 }
931
932 static int mathutils_kxblendermaterial_color_get_index(BaseMathObject *bmo, int subtype, int index)
933 {
934         /* lazy, avoid repeteing the case statement */
935         if (mathutils_kxblendermaterial_color_get(bmo, subtype) == -1)
936                 return -1;
937         return 0;
938 }
939
940 static int mathutils_kxblendermaterial_color_set_index(BaseMathObject *bmo, int subtype, int index)
941 {
942         float f = bmo->data[index];
943
944         /* lazy, avoid repeateing the case statement */
945         if (mathutils_kxblendermaterial_color_get(bmo, subtype) == -1)
946                 return -1;
947
948         bmo->data[index] = f;
949         return mathutils_kxblendermaterial_color_set(bmo, subtype);
950 }
951
952 static Mathutils_Callback mathutils_kxblendermaterial_color_cb = {
953         mathutils_kxblendermaterial_generic_check,
954         mathutils_kxblendermaterial_color_get,
955         mathutils_kxblendermaterial_color_set,
956         mathutils_kxblendermaterial_color_get_index,
957         mathutils_kxblendermaterial_color_set_index
958 };
959
960
961 void KX_BlenderMaterial_Mathutils_Callback_Init()
962 {
963         // register mathutils callbacks, ok to run more than once.
964         mathutils_kxblendermaterial_color_cb_index = Mathutils_RegisterCallback(&mathutils_kxblendermaterial_color_cb);
965 }
966
967 #endif // USE_MATHUTILS
968
969 #ifdef WITH_PYTHON
970
971 PyMethodDef KX_BlenderMaterial::Methods[] = 
972 {
973         KX_PYMETHODTABLE( KX_BlenderMaterial, getShader ),
974         KX_PYMETHODTABLE( KX_BlenderMaterial, getMaterialIndex ),
975         KX_PYMETHODTABLE( KX_BlenderMaterial, getTextureBindcode ),
976         KX_PYMETHODTABLE( KX_BlenderMaterial, setBlending ),
977         {NULL,NULL} //Sentinel
978 };
979
980 PyAttributeDef KX_BlenderMaterial::Attributes[] = {
981         KX_PYATTRIBUTE_RO_FUNCTION("shader", KX_BlenderMaterial, pyattr_get_shader),
982         KX_PYATTRIBUTE_RO_FUNCTION("material_index", KX_BlenderMaterial, pyattr_get_materialIndex),
983         KX_PYATTRIBUTE_RW_FUNCTION("blending", KX_BlenderMaterial, pyattr_get_blending, pyattr_set_blending),
984         KX_PYATTRIBUTE_RW_FUNCTION("alpha", KX_BlenderMaterial, pyattr_get_alpha, pyattr_set_alpha),
985         KX_PYATTRIBUTE_RW_FUNCTION("hardness", KX_BlenderMaterial, pyattr_get_hardness, pyattr_set_hardness),
986         KX_PYATTRIBUTE_RW_FUNCTION("specularIntensity", KX_BlenderMaterial, pyattr_get_specular_intensity, pyattr_set_specular_intensity),
987         KX_PYATTRIBUTE_RW_FUNCTION("specularColor", KX_BlenderMaterial, pyattr_get_specular_color, pyattr_set_specular_color),
988         KX_PYATTRIBUTE_RW_FUNCTION("diffuseIntensity", KX_BlenderMaterial, pyattr_get_diffuse_intensity, pyattr_set_diffuse_intensity),
989         KX_PYATTRIBUTE_RW_FUNCTION("diffuseColor", KX_BlenderMaterial, pyattr_get_diffuse_color, pyattr_set_diffuse_color),
990         KX_PYATTRIBUTE_RW_FUNCTION("emit", KX_BlenderMaterial, pyattr_get_emit, pyattr_set_emit),
991
992         { NULL }        //Sentinel
993 };
994
995 PyTypeObject KX_BlenderMaterial::Type = {
996         PyVarObject_HEAD_INIT(NULL, 0)
997         "KX_BlenderMaterial",
998         sizeof(PyObjectPlus_Proxy),
999         0,
1000         py_base_dealloc,
1001         0,
1002         0,
1003         0,
1004         0,
1005         py_base_repr,
1006         0,0,0,0,0,0,0,0,0,
1007         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
1008         0,0,0,0,0,0,0,
1009         Methods,
1010         0,
1011         0,
1012         &PyObjectPlus::Type,
1013         0,0,0,0,0,0,
1014         py_base_new
1015 };
1016
1017 PyObject *KX_BlenderMaterial::pyattr_get_shader(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1018 {
1019         KX_BlenderMaterial* self = static_cast<KX_BlenderMaterial*>(self_v);
1020         return self->PygetShader(NULL, NULL);
1021 }
1022
1023 PyObject *KX_BlenderMaterial::pyattr_get_materialIndex(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1024 {
1025         KX_BlenderMaterial* self = static_cast<KX_BlenderMaterial*>(self_v);
1026         return PyLong_FromLong(self->GetMaterialIndex());
1027 }
1028
1029 PyObject *KX_BlenderMaterial::pyattr_get_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1030 {
1031         KX_BlenderMaterial* self = static_cast<KX_BlenderMaterial*>(self_v);
1032         unsigned int* bfunc = self->getBlendFunc();
1033         return Py_BuildValue("(ll)", (long int)bfunc[0], (long int)bfunc[1]);
1034 }
1035
1036 PyObject *KX_BlenderMaterial::pyattr_get_alpha(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1037 {
1038         KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
1039         return PyFloat_FromDouble(self->GetBLMaterial()->alpha);
1040 }
1041
1042 int KX_BlenderMaterial::pyattr_set_alpha(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1043 {
1044         KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
1045         float val = PyFloat_AsDouble(value);
1046
1047         if (val == -1 && PyErr_Occurred()) {
1048                 PyErr_Format(PyExc_AttributeError, "material.%s = float: KX_BlenderMaterial, expected a float", attrdef->m_name);
1049                 return PY_SET_ATTR_FAIL;
1050         }
1051
1052         CLAMP(val, 0.0f, 1.0f);
1053
1054         BL_Material *mat = self->GetBLMaterial();
1055         mat->alpha = mat->material->alpha = val;
1056         return PY_SET_ATTR_SUCCESS;
1057 }
1058 PyObject *KX_BlenderMaterial::pyattr_get_hardness(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1059 {
1060         KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
1061         return PyLong_FromLong(self->GetBLMaterial()->hard);
1062 }
1063
1064 int KX_BlenderMaterial::pyattr_set_hardness(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1065 {
1066         KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
1067         int val = PyLong_AsLong(value);
1068
1069         if (val == -1 && PyErr_Occurred()) {
1070                 PyErr_Format(PyExc_AttributeError, "material.%s = int: KX_BlenderMaterial, expected a int", attrdef->m_name);
1071                 return PY_SET_ATTR_FAIL;
1072         }
1073
1074         CLAMP(val, 1, 511);
1075
1076         BL_Material *mat = self->GetBLMaterial();
1077         mat->hard = mat->material->har = val;
1078         return PY_SET_ATTR_SUCCESS;
1079 }
1080
1081 PyObject *KX_BlenderMaterial::pyattr_get_specular_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1082 {
1083         KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
1084         return PyFloat_FromDouble(self->GetBLMaterial()->spec_f);
1085 }
1086
1087 int KX_BlenderMaterial::pyattr_set_specular_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1088 {
1089         KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
1090         float val = PyFloat_AsDouble(value);
1091
1092         if (val == -1 && PyErr_Occurred()) {
1093                 PyErr_Format(PyExc_AttributeError, "material.%s = float: KX_BlenderMaterial, expected a float", attrdef->m_name);
1094                 return PY_SET_ATTR_FAIL;
1095         }
1096
1097         CLAMP(val, 0.0f, 1.0f);
1098
1099         BL_Material *mat = self->GetBLMaterial();
1100         mat->spec_f = mat->material->spec = val;
1101         return PY_SET_ATTR_SUCCESS;
1102 }
1103
1104 PyObject *KX_BlenderMaterial::pyattr_get_specular_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1105 {
1106 #ifdef USE_MATHUTILS
1107         return Color_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), mathutils_kxblendermaterial_color_cb_index, MATHUTILS_COL_CB_MATERIAL_SPECULAR_COLOR);
1108 #else
1109         KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
1110         return PyColorFromVector(MT_Vector3(self->GetBLMaterial()->speccolor));
1111 #endif
1112 }
1113
1114 int KX_BlenderMaterial::pyattr_set_specular_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1115 {
1116         KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
1117         MT_Vector3 color;
1118         if (!PyVecTo(value, color))
1119                 return PY_SET_ATTR_FAIL;
1120
1121         BL_Material *mat = self->GetBLMaterial();
1122         color.getValue(mat->speccolor);
1123         mat->material->specr = color[0];
1124         mat->material->specg = color[1];
1125         mat->material->specb = color[2];
1126         return PY_SET_ATTR_SUCCESS;
1127 }
1128
1129 PyObject *KX_BlenderMaterial::pyattr_get_diffuse_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1130 {
1131         KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
1132         return PyFloat_FromDouble(self->GetBLMaterial()->ref);
1133 }
1134
1135 int KX_BlenderMaterial::pyattr_set_diffuse_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1136 {
1137         KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
1138         float val = PyFloat_AsDouble(value);
1139
1140         if (val == -1 && PyErr_Occurred()) {
1141                 PyErr_Format(PyExc_AttributeError, "material.%s = float: KX_BlenderMaterial, expected a float", attrdef->m_name);
1142                 return PY_SET_ATTR_FAIL;
1143         }
1144
1145         CLAMP(val, 0.0f, 1.0f);
1146
1147         BL_Material *mat = self->GetBLMaterial();
1148         mat->ref = mat->material->ref = val;
1149         return PY_SET_ATTR_SUCCESS;
1150 }
1151
1152 PyObject *KX_BlenderMaterial::pyattr_get_diffuse_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1153 {
1154 #ifdef USE_MATHUTILS
1155         return Color_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), mathutils_kxblendermaterial_color_cb_index, MATHUTILS_COL_CB_MATERIAL_DIFFUSE_COLOR);
1156 #else
1157         KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
1158         return PyColorFromVector(MT_Vector3(self->GetBLMaterial()->matcolor));
1159 #endif
1160 }
1161
1162 int KX_BlenderMaterial::pyattr_set_diffuse_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1163 {
1164         KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
1165         MT_Vector3 color;
1166         if (!PyVecTo(value, color))
1167                 return PY_SET_ATTR_FAIL;
1168
1169         BL_Material *mat = self->GetBLMaterial();
1170         color.getValue(mat->matcolor);
1171         mat->material->r = color[0];
1172         mat->material->g = color[1];
1173         mat->material->b = color[2];
1174         return PY_SET_ATTR_SUCCESS;
1175 }
1176
1177 PyObject *KX_BlenderMaterial::pyattr_get_emit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1178 {
1179         KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
1180         return PyFloat_FromDouble(self->GetBLMaterial()->emit);
1181 }
1182
1183 int KX_BlenderMaterial::pyattr_set_emit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1184 {
1185         KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
1186         float val = PyFloat_AsDouble(value);
1187
1188         if (val == -1 && PyErr_Occurred()) {
1189                 PyErr_Format(PyExc_AttributeError, "material.%s = float: KX_BlenderMaterial, expected a float", attrdef->m_name);
1190                 return PY_SET_ATTR_FAIL;
1191         }
1192
1193         CLAMP(val, 0.0f, 2.0f);
1194
1195         BL_Material *mat = self->GetBLMaterial();
1196         mat->emit = mat->material->emit = val;
1197         return PY_SET_ATTR_SUCCESS;
1198 }
1199
1200 int KX_BlenderMaterial::pyattr_set_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1201 {
1202         KX_BlenderMaterial* self = static_cast<KX_BlenderMaterial*>(self_v);
1203         PyObject *obj = self->PysetBlending(value, NULL);
1204         if (obj)
1205         {
1206                 Py_DECREF(obj);
1207                 return 0;
1208         }
1209         return -1;
1210 }
1211
1212 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()")
1213 {
1214         if ( !GLEW_ARB_fragment_shader) {
1215                 if (!mModified)
1216                         spit("Fragment shaders not supported");
1217         
1218                 mModified = true;
1219                 Py_RETURN_NONE;
1220         }
1221
1222         if ( !GLEW_ARB_vertex_shader) {
1223                 if (!mModified)
1224                         spit("Vertex shaders not supported");
1225
1226                 mModified = true;
1227                 Py_RETURN_NONE;
1228         }
1229
1230         if (!GLEW_ARB_shader_objects) {
1231                 if (!mModified)
1232                         spit("GLSL not supported");
1233                 mModified = true;
1234                 Py_RETURN_NONE;
1235         }
1236         else {
1237                 // returns Py_None on error
1238                 // the calling script will need to check
1239
1240                 if (!mShader && !mModified) {
1241                         mShader = new BL_Shader();
1242                         mModified = true;
1243
1244                         // Using a custom shader, make sure to initialize textures
1245                         InitTextures();
1246                 }
1247
1248                 if (mShader && !mShader->GetError()) {
1249                         m_flag &= ~RAS_BLENDERGLSL;
1250                         mMaterial->SetSharedMaterial(true);
1251                         mScene->GetBucketManager()->ReleaseDisplayLists(this);
1252                         return mShader->GetProxy();
1253                 }
1254                 else {
1255                         // decref all references to the object
1256                         // then delete it!
1257                         // We will then go back to fixed functionality
1258                         // for this material
1259                         if (mShader) {
1260                                 delete mShader; /* will handle python de-referencing */
1261                                 mShader=0;
1262                         }
1263                 }
1264                 Py_RETURN_NONE;
1265         }
1266         PyErr_SetString(PyExc_ValueError, "material.getShader(): KX_BlenderMaterial, GLSL Error");
1267         return NULL;
1268 }
1269
1270 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getMaterialIndex, "getMaterialIndex()")
1271 {
1272         return PyLong_FromLong(GetMaterialIndex());
1273 }
1274
1275 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getTexture, "getTexture( index )" )
1276 {
1277         // TODO: enable python switching
1278         return NULL;
1279 }
1280
1281 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, setTexture , "setTexture( index, tex)")
1282 {
1283         // TODO: enable python switching
1284         return NULL;
1285 }
1286
1287 static const unsigned int GL_array[11] = {
1288         GL_ZERO,
1289         GL_ONE,
1290         GL_SRC_COLOR,
1291         GL_ONE_MINUS_SRC_COLOR,
1292         GL_DST_COLOR,
1293         GL_ONE_MINUS_DST_COLOR,
1294         GL_SRC_ALPHA,
1295         GL_ONE_MINUS_SRC_ALPHA,
1296         GL_DST_ALPHA,
1297         GL_ONE_MINUS_DST_ALPHA,
1298         GL_SRC_ALPHA_SATURATE
1299 };
1300
1301 KX_PYMETHODDEF_DOC( KX_BlenderMaterial, setBlending , "setBlending( bge.logic.src, bge.logic.dest)")
1302 {
1303         unsigned int b[2];
1304         if (PyArg_ParseTuple(args, "ii:setBlending", &b[0], &b[1]))
1305         {
1306                 bool value_found[2] = {false, false};
1307                 for (int i=0; i<11; i++)
1308                 {
1309                         if (b[0] == GL_array[i]) {
1310                                 value_found[0] = true;
1311                                 mBlendFunc[0] = b[0];
1312                         }
1313                         if (b[1] == GL_array[i]) {
1314                                 value_found[1] = true;
1315                                 mBlendFunc[1] = b[1];
1316                         }
1317                         if (value_found[0] && value_found[1]) break;
1318                 }
1319                 if (!value_found[0] || !value_found[1]) {
1320                         PyErr_SetString(PyExc_ValueError, "material.setBlending(int, int): KX_BlenderMaterial, invalid enum.");
1321                         return NULL;
1322                 }
1323                 mUserDefBlend = true;
1324                 Py_RETURN_NONE;
1325         }
1326         return NULL;
1327 }
1328
1329 KX_PYMETHODDEF_DOC(KX_BlenderMaterial, getTextureBindcode, "getTextureBindcode(texslot)")
1330 {
1331         unsigned int texslot;
1332         if (!PyArg_ParseTuple(args, "i:texslot", &texslot)) {
1333                 PyErr_SetString(PyExc_ValueError, "material.getTextureBindcode(texslot): KX_BlenderMaterial, expected an int.");
1334                 return NULL;
1335         }
1336         Image *ima = getImage(texslot);
1337         if (ima) {
1338                 unsigned int *bindcode = ima->bindcode;
1339                 return PyLong_FromLong(*bindcode);
1340         }
1341         PyErr_SetString(PyExc_ValueError, "material.getTextureBindcode(texslot): KX_BlenderMaterial, invalid texture slot.");
1342         return NULL;
1343 }
1344
1345 #endif // WITH_PYTHON