removing files that should not be in blender2.5, added (by mistake?) r19226
[blender.git] / source / gameengine / Ketsji / BL_Shader.cpp
1
2 #include "GL/glew.h"
3
4 #include <iostream>
5 #include "BL_Shader.h"
6 #include "BL_Material.h"
7
8 #include "MT_assert.h"
9 #include "MT_Matrix4x4.h"
10 #include "MT_Matrix3x3.h"
11 #include "KX_PyMath.h"
12 #include "MEM_guardedalloc.h"
13
14 #include "RAS_GLExtensionManager.h"
15 #include "RAS_MeshObject.h"
16 #include "RAS_IRasterizer.h"
17
18 #define spit(x) std::cout << x << std::endl;
19
20 #define SORT_UNIFORMS 1
21 #define UNIFORM_MAX_LEN (int)sizeof(float)*16
22 #define MAX_LOG_LEN 262144 // bounds
23
24 BL_Uniform::BL_Uniform(int data_size)
25 :       mLoc(-1),
26         mDirty(true),
27         mType(UNI_NONE),
28         mTranspose(0),
29         mDataLen(data_size)
30 {
31 #ifdef SORT_UNIFORMS
32         MT_assert((int)mDataLen <= UNIFORM_MAX_LEN);
33         mData = (void*)MEM_mallocN(mDataLen, "shader-uniform-alloc");
34 #endif
35 }
36
37 BL_Uniform::~BL_Uniform()
38 {
39 #ifdef SORT_UNIFORMS
40         if(mData) {
41                 MEM_freeN(mData);
42                 mData=0;
43         }
44 #endif
45 }
46
47 void BL_Uniform::Apply(class BL_Shader *shader)
48 {
49 #ifdef SORT_UNIFORMS
50         MT_assert(mType > UNI_NONE && mType < UNI_MAX && mData);
51
52         if(!mDirty) 
53                 return;
54
55         switch(mType)
56         {
57         case UNI_FLOAT: {
58                         float *f = (float*)mData;
59                         glUniform1fARB(mLoc,(GLfloat)*f);
60                 }break;
61         case UNI_INT: {
62                         int *f = (int*)mData;
63                         glUniform1iARB(mLoc, (GLint)*f);
64                 }break;
65         case UNI_FLOAT2: {
66                         float *f = (float*)mData;
67                         glUniform2fvARB(mLoc,1, (GLfloat*)f);
68                 }break;
69         case UNI_FLOAT3: {
70                         float *f = (float*)mData;
71                         glUniform3fvARB(mLoc,1,(GLfloat*)f);
72                 }break;
73         case UNI_FLOAT4: {
74                         float *f = (float*)mData;
75                         glUniform4fvARB(mLoc,1,(GLfloat*)f);
76                 }break;
77         case UNI_INT2: {
78                         int *f = (int*)mData;
79                         glUniform2ivARB(mLoc,1,(GLint*)f);
80                 }break; 
81         case UNI_INT3: {
82                         int *f = (int*)mData;
83                         glUniform3ivARB(mLoc,1,(GLint*)f);
84                 }break; 
85         case UNI_INT4: {
86                         int *f = (int*)mData;
87                         glUniform4ivARB(mLoc,1,(GLint*)f);
88                 }break;
89         case UNI_MAT4: {
90                         float *f = (float*)mData;
91                         glUniformMatrix4fvARB(mLoc, 1, mTranspose?GL_TRUE:GL_FALSE,(GLfloat*)f);
92                 }break;
93         case UNI_MAT3: {
94                         float *f = (float*)mData;
95                         glUniformMatrix3fvARB(mLoc, 1, mTranspose?GL_TRUE:GL_FALSE,(GLfloat*)f);
96                 }break;
97         }
98         mDirty = false;
99 #endif
100 }
101
102 void BL_Uniform::SetData(int location, int type,bool transpose)
103 {
104 #ifdef SORT_UNIFORMS
105         mType   = type;
106         mLoc    = location;
107         mDirty  = true;
108 #endif
109 }
110
111 bool BL_Shader::Ok()const
112 {
113         return (mShader !=0 && mOk && mUse);
114 }
115
116 BL_Shader::BL_Shader(PyTypeObject *T)
117 :       PyObjectPlus(T),
118         mShader(0),
119         mPass(1),
120         mOk(0),
121         mUse(0),
122         mAttr(0),
123         vertProg(""),
124         fragProg(""),
125         mError(0),
126         mDirty(true)
127 {
128         // if !GLEW_ARB_shader_objects this class will not be used
129         //for (int i=0; i<MAXTEX; i++) {
130         //      mSampler[i] = BL_Sampler();
131         //}
132 }
133
134 BL_Shader::~BL_Shader()
135 {
136         //for (int i=0; i<MAXTEX; i++){
137         //      if(mSampler[i].mOwn) {
138         //              if(mSampler[i].mTexture)
139         //                      mSampler[i].mTexture->DeleteTex();
140         //      }
141         //}
142         ClearUniforms();
143
144         if( mShader ) {
145                 glDeleteObjectARB(mShader);
146                 mShader = 0;
147         }
148         vertProg        = 0;
149         fragProg        = 0;
150         mOk                     = 0;
151         glUseProgramObjectARB(0);
152 }
153
154 void BL_Shader::ClearUniforms()
155 {
156         BL_UniformVec::iterator it = mUniforms.begin();
157         while(it != mUniforms.end()){
158                 delete (*it);
159                 it++;
160         }
161         mUniforms.clear();
162
163         
164         BL_UniformVecDef::iterator itp = mPreDef.begin();
165         while(itp != mPreDef.end()) {
166                 delete (*itp);
167                 itp++;
168         }
169         mPreDef.clear();
170
171 }
172
173
174 BL_Uniform  *BL_Shader::FindUniform(const int location)
175 {
176 #ifdef SORT_UNIFORMS
177         BL_UniformVec::iterator it = mUniforms.begin();
178         while(it != mUniforms.end()) {
179                 if((*it)->GetLocation() == location)
180                         return (*it);
181                 it++;
182         }
183 #endif
184         return 0;
185 }
186
187 void BL_Shader::SetUniformfv(int location, int type, float *param,int size, bool transpose)
188 {
189 #ifdef SORT_UNIFORMS
190         BL_Uniform *uni= FindUniform(location);
191         if(uni) {
192                 memcpy(uni->getData(), param, size);
193                 uni->SetData(location, type, transpose);
194         }
195         else {
196                 uni = new BL_Uniform(size);
197                 memcpy(uni->getData(), param, size);
198
199                 uni->SetData(location, type, transpose);
200                 mUniforms.push_back(uni);
201         }
202         mDirty = true;
203 #endif
204 }
205
206 void BL_Shader::SetUniformiv(int location, int type, int *param,int size, bool transpose)
207 {
208 #ifdef SORT_UNIFORMS
209         BL_Uniform *uni= FindUniform(location);
210         if(uni) {
211                 memcpy(uni->getData(), param, size);
212                 uni->SetData(location, type, transpose);
213         }
214         else {
215                 uni = new BL_Uniform(size);
216                 memcpy(uni->getData(), param, size);
217                 uni->SetData(location, type, transpose);
218                 mUniforms.push_back(uni);
219         }
220         mDirty = true;
221 #endif
222 }
223
224
225 void BL_Shader::ApplyShader()
226 {
227 #ifdef SORT_UNIFORMS
228         if(!mDirty) 
229                 return;
230
231         for(unsigned int i=0; i<mUniforms.size(); i++)
232                 mUniforms[i]->Apply(this);
233
234         mDirty = false;
235 #endif
236 }
237
238 void BL_Shader::UnloadShader()
239 {
240         //
241 }
242
243
244 bool BL_Shader::LinkProgram()
245 {
246         int vertlen = 0, fraglen=0, proglen=0;
247         int vertstatus=0, fragstatus=0, progstatus=0;
248         unsigned int tmpVert=0, tmpFrag=0, tmpProg=0;
249         int char_len=0;
250         char *logInf =0;
251
252         if(mError)
253                 goto programError;
254
255         if(!vertProg || !fragProg){
256                 spit("Invalid GLSL sources");
257                 return false;
258         }
259         if( !GLEW_ARB_fragment_shader) {
260                 spit("Fragment shaders not supported");
261                 return false;
262         }
263         if( !GLEW_ARB_vertex_shader) {
264                 spit("Vertex shaders not supported");
265                 return false;
266         }
267         
268         // -- vertex shader ------------------
269         tmpVert = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
270         glShaderSourceARB(tmpVert, 1, (const char**)&vertProg, 0);
271         glCompileShaderARB(tmpVert);
272         glGetObjectParameterivARB(tmpVert, GL_OBJECT_INFO_LOG_LENGTH_ARB,(GLint*) &vertlen);
273         
274         // print info if any
275         if( vertlen > 0 && vertlen < MAX_LOG_LEN){
276                 logInf = (char*)MEM_mallocN(vertlen, "vert-log");
277                 glGetInfoLogARB(tmpVert, vertlen, (GLsizei*)&char_len, logInf);
278                 if(char_len >0) {
279                         spit("---- Vertex Shader Error ----");
280                         spit(logInf);
281                 }
282                 MEM_freeN(logInf);
283                 logInf=0;
284         }
285         // check for compile errors
286         glGetObjectParameterivARB(tmpVert, GL_OBJECT_COMPILE_STATUS_ARB,(GLint*)&vertstatus);
287         if(!vertstatus) {
288                 spit("---- Vertex shader failed to compile ----");
289                 goto programError;
290         }
291
292         // -- fragment shader ----------------
293         tmpFrag = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
294         glShaderSourceARB(tmpFrag, 1,(const char**)&fragProg, 0);
295         glCompileShaderARB(tmpFrag);
296         glGetObjectParameterivARB(tmpFrag, GL_OBJECT_INFO_LOG_LENGTH_ARB, (GLint*) &fraglen);
297         if(fraglen >0 && fraglen < MAX_LOG_LEN){
298                 logInf = (char*)MEM_mallocN(fraglen, "frag-log");
299                 glGetInfoLogARB(tmpFrag, fraglen,(GLsizei*) &char_len, logInf);
300                 if(char_len >0) {
301                         spit("---- Fragment Shader Error ----");
302                         spit(logInf);
303                 }
304                 MEM_freeN(logInf);
305                 logInf=0;
306         }
307
308         glGetObjectParameterivARB(tmpFrag, GL_OBJECT_COMPILE_STATUS_ARB, (GLint*) &fragstatus);
309         if(!fragstatus){
310                 spit("---- Fragment shader failed to compile ----");
311                 goto programError;
312         }
313
314         
315         // -- program ------------------------
316         //  set compiled vert/frag shader & link
317         tmpProg = glCreateProgramObjectARB();
318         glAttachObjectARB(tmpProg, tmpVert);
319         glAttachObjectARB(tmpProg, tmpFrag);
320         glLinkProgramARB(tmpProg);
321         glGetObjectParameterivARB(tmpProg, GL_OBJECT_INFO_LOG_LENGTH_ARB, (GLint*) &proglen);
322         glGetObjectParameterivARB(tmpProg, GL_OBJECT_LINK_STATUS_ARB, (GLint*) &progstatus);
323         
324
325         if(proglen > 0 && proglen < MAX_LOG_LEN) {
326                 logInf = (char*)MEM_mallocN(proglen, "prog-log");
327                 glGetInfoLogARB(tmpProg, proglen, (GLsizei*)&char_len, logInf);
328                 if(char_len >0) {
329                         spit("---- GLSL Program ----");
330                         spit(logInf);
331                 }
332                 MEM_freeN(logInf);
333                 logInf=0;
334         }
335
336         if(!progstatus){
337                 spit("---- GLSL program failed to link ----");
338                 goto programError;
339         }
340
341         // set
342         mShader = tmpProg;
343         glDeleteObjectARB(tmpVert);
344         glDeleteObjectARB(tmpFrag);
345         mOk             = 1;
346         mError = 0;
347         return true;
348
349 programError:
350         if(tmpVert) {
351                 glDeleteObjectARB(tmpVert);
352                 tmpVert=0;
353         }
354         if(tmpFrag) {
355                 glDeleteObjectARB(tmpFrag);
356                 tmpFrag=0;
357         }
358
359         if(tmpProg) {
360                 glDeleteObjectARB(tmpProg);
361                 tmpProg=0;
362         }
363
364         mOk             = 0;
365         mUse    = 0;
366         mError  = 1;
367         return false;
368 }
369
370 const char *BL_Shader::GetVertPtr()
371 {
372         return vertProg?vertProg:0;
373 }
374
375 const char *BL_Shader::GetFragPtr()
376 {
377         return fragProg?fragProg:0;
378 }
379
380 void BL_Shader::SetVertPtr( char *vert )
381 {
382         vertProg = vert;
383 }
384
385 void BL_Shader::SetFragPtr( char *frag )
386 {
387         fragProg = frag;
388 }
389
390 unsigned int BL_Shader::GetProg()
391
392         return mShader;
393 }
394 //
395 //const BL_Sampler* BL_Shader::GetSampler(int i)
396 //{
397 //      MT_assert(i<=MAXTEX);
398 //      return &mSampler[i];
399 //}
400
401 void BL_Shader::SetSampler(int loc, int unit)
402 {
403         if( GLEW_ARB_fragment_shader &&
404                 GLEW_ARB_vertex_shader &&
405                 GLEW_ARB_shader_objects 
406                 )
407         {
408                 glUniform1iARB(loc, unit);
409         }
410 }
411 //
412 //void BL_Shader::InitializeSampler(int unit, BL_Texture* texture)
413 //{
414 //      MT_assert(unit<=MAXTEX);
415 //      mSampler[unit].mTexture = texture;
416 //      mSampler[unit].mLoc =-1;
417 //      mSampler[unit].mOwn = 0;
418 //}
419
420 void BL_Shader::SetProg(bool enable)
421 {
422         if( GLEW_ARB_fragment_shader &&
423                 GLEW_ARB_vertex_shader &&
424                 GLEW_ARB_shader_objects 
425                 )
426         {
427                 if(     mShader != 0 && mOk && enable) {
428                         glUseProgramObjectARB(mShader);
429                 }
430                 else {
431                         glUseProgramObjectARB(0);       
432                 }
433         }
434 }
435
436 void BL_Shader::Update( const RAS_MeshSlot & ms, RAS_IRasterizer* rasty )
437 {
438         if(!Ok() || !mPreDef.size()) 
439                 return;
440
441         if( GLEW_ARB_fragment_shader &&
442                 GLEW_ARB_vertex_shader &&
443                 GLEW_ARB_shader_objects 
444                 )
445         {
446                 MT_Matrix4x4 model;
447                 model.setValue(ms.m_OpenGLMatrix);
448                 const MT_Matrix4x4& view = rasty->GetViewMatrix();
449
450                 if(mAttr==SHD_TANGENT)
451                          ms.m_mesh->SetMeshModified(true);
452
453                 BL_UniformVecDef::iterator it;
454                 for(it = mPreDef.begin(); it!= mPreDef.end(); it++)
455                 {
456                         BL_DefUniform *uni = (*it);
457                         if(uni->mLoc == -1) continue;
458
459                         switch (uni->mType)
460                         {
461                                 case MODELMATRIX:
462                                         {
463                                                 SetUniform(uni->mLoc, model);
464                                                 break;
465                                         }
466                                 case MODELMATRIX_TRANSPOSE:
467                                         {
468                                                 SetUniform(uni->mLoc, model, true);
469                                                 break;
470                                         }
471                                 case MODELMATRIX_INVERSE:
472                                         {
473                                                 model.invert();
474                                                 SetUniform(uni->mLoc, model);
475                                                 break;
476                                         }
477                                 case MODELMATRIX_INVERSETRANSPOSE:
478                                         {
479                                                 model.invert();
480                                                 SetUniform(uni->mLoc, model, true);
481                                                 break;
482                                         }
483                                 case MODELVIEWMATRIX:
484                                         {
485                                                 SetUniform(uni->mLoc, view*model);
486                                                 break;
487                                         }
488
489                                 case MODELVIEWMATRIX_TRANSPOSE:
490                                         {
491                                                 MT_Matrix4x4 mat(view*model);
492                                                 SetUniform(uni->mLoc, mat, true);
493                                                 break;
494                                         }
495                                 case MODELVIEWMATRIX_INVERSE:
496                                         {
497                                                 MT_Matrix4x4 mat(view*model);
498                                                 mat.invert();
499                                                 SetUniform(uni->mLoc, mat);
500                                                 break;
501                                         }
502                                 case MODELVIEWMATRIX_INVERSETRANSPOSE:
503                                         {
504                                                 MT_Matrix4x4 mat(view*model);
505                                                 mat.invert();
506                                                 SetUniform(uni->mLoc, mat, true);
507                                                 break;
508                                         }
509                                 case CAM_POS:
510                                         {
511                                                 MT_Point3 pos(rasty->GetCameraPosition());
512                                                 SetUniform(uni->mLoc, pos);
513                                                 break;
514                                         }
515                                 case VIEWMATRIX:
516                                         {
517                                                 SetUniform(uni->mLoc, view);
518                                                 break;
519                                         }
520                                 case VIEWMATRIX_TRANSPOSE:
521                                         {
522                                                 SetUniform(uni->mLoc, view, true);
523                                                 break;
524                                         }
525                                 case VIEWMATRIX_INVERSE:
526                                         {
527                                                 MT_Matrix4x4 viewinv = view;
528                                                 viewinv.invert();
529                                                 SetUniform(uni->mLoc, view);
530                                                 break;
531                                         }
532                                 case VIEWMATRIX_INVERSETRANSPOSE:
533                                         {
534                                                 MT_Matrix4x4 viewinv = view;
535                                                 viewinv.invert();
536                                                 SetUniform(uni->mLoc, view, true);
537                                                 break;
538                                         }
539                                 case CONSTANT_TIMER:
540                                         {
541                                                 SetUniform(uni->mLoc, (float)rasty->GetTime());
542                                                 break;
543                                         }
544                                 default:
545                                         break;
546                         }
547                 }
548         }
549 }
550
551
552 int BL_Shader::GetAttribLocation(const STR_String& name)
553 {
554         if( GLEW_ARB_fragment_shader &&
555                 GLEW_ARB_vertex_shader &&
556                 GLEW_ARB_shader_objects 
557                 )
558         {
559                 return glGetAttribLocationARB(mShader, name.ReadPtr());
560         }
561
562         return -1;
563 }
564
565 void BL_Shader::BindAttribute(const STR_String& attr, int loc)
566 {
567         if( GLEW_ARB_fragment_shader &&
568                 GLEW_ARB_vertex_shader &&
569                 GLEW_ARB_shader_objects 
570                 )
571         {
572                 glBindAttribLocationARB(mShader, loc, attr.ReadPtr());
573         }
574 }
575
576 int BL_Shader::GetUniformLocation(const STR_String& name)
577 {
578         if( GLEW_ARB_fragment_shader &&
579                 GLEW_ARB_vertex_shader &&
580                 GLEW_ARB_shader_objects 
581                 )
582         {
583                 MT_assert(mShader!=0);
584                 int location = glGetUniformLocationARB(mShader, name.ReadPtr());
585                 if(location == -1)
586                         spit("Invalid uniform value: " << name.ReadPtr() << ".");
587                 return location;
588         }
589
590         return -1;
591 }
592
593 void BL_Shader::SetUniform(int uniform, const MT_Tuple2& vec)
594 {
595         if( GLEW_ARB_fragment_shader &&
596                 GLEW_ARB_vertex_shader &&
597                 GLEW_ARB_shader_objects 
598                 )
599         {
600                 float value[2];
601                 vec.getValue(value);
602                 glUniform2fvARB(uniform, 1, value);
603         }
604
605 }
606
607 void BL_Shader::SetUniform(int uniform, const MT_Tuple3& vec)
608 {
609         if( GLEW_ARB_fragment_shader &&
610                 GLEW_ARB_vertex_shader &&
611                 GLEW_ARB_shader_objects 
612                 )
613         {       
614                 float value[3];
615                 vec.getValue(value);
616                 glUniform3fvARB(uniform, 1, value);
617         }
618 }
619
620 void BL_Shader::SetUniform(int uniform, const MT_Tuple4& vec)
621 {
622         if( GLEW_ARB_fragment_shader &&
623                 GLEW_ARB_vertex_shader &&
624                 GLEW_ARB_shader_objects 
625                 )
626         {
627                 float value[4];
628                 vec.getValue(value);
629                 glUniform4fvARB(uniform, 1, value);
630         }
631 }
632
633 void BL_Shader::SetUniform(int uniform, const unsigned int& val)
634 {
635         if( GLEW_ARB_fragment_shader &&
636                 GLEW_ARB_vertex_shader &&
637                 GLEW_ARB_shader_objects 
638                 )
639         {
640                 glUniform1iARB(uniform, val);
641         }
642 }
643
644 void BL_Shader::SetUniform(int uniform, const int val)
645 {
646         if( GLEW_ARB_fragment_shader &&
647                 GLEW_ARB_vertex_shader &&
648                 GLEW_ARB_shader_objects 
649                 )
650         {
651                 glUniform1iARB(uniform, val);
652         }
653 }
654
655 void BL_Shader::SetUniform(int uniform, const float& val)
656 {
657         if( GLEW_ARB_fragment_shader &&
658                 GLEW_ARB_vertex_shader &&
659                 GLEW_ARB_shader_objects 
660                 )
661         {
662                 glUniform1fARB(uniform, val);
663         }
664 }
665
666 void BL_Shader::SetUniform(int uniform, const MT_Matrix4x4& vec, bool transpose)
667 {
668         if( GLEW_ARB_fragment_shader &&
669                 GLEW_ARB_vertex_shader &&
670                 GLEW_ARB_shader_objects 
671                 )
672         {
673                 float value[16];
674                 // note: getValue gives back column major as needed by OpenGL
675                 vec.getValue(value);
676                 glUniformMatrix4fvARB(uniform, 1, transpose?GL_TRUE:GL_FALSE, value);
677         }
678 }
679
680 void BL_Shader::SetUniform(int uniform, const MT_Matrix3x3& vec, bool transpose)
681 {
682         if( GLEW_ARB_fragment_shader &&
683                 GLEW_ARB_vertex_shader &&
684                 GLEW_ARB_shader_objects 
685                 )
686         {
687                 float value[9];
688                 value[0] = (float)vec[0][0]; value[1] = (float)vec[1][0]; value[2] = (float)vec[2][0]; 
689                 value[3] = (float)vec[0][1]; value[4] = (float)vec[1][1]; value[5] = (float)vec[2][1]; 
690                 value[6] = (float)vec[0][2]; value[7] = (float)vec[1][2]; value[7] = (float)vec[2][2]; 
691                 glUniformMatrix3fvARB(uniform, 1, transpose?GL_TRUE:GL_FALSE, value);
692         }
693 }
694
695 void BL_Shader::SetUniform(int uniform, const float* val, int len)
696 {
697         if( GLEW_ARB_fragment_shader &&
698                 GLEW_ARB_vertex_shader &&
699                 GLEW_ARB_shader_objects 
700                 )
701         {
702                 if(len == 2) 
703                         glUniform2fvARB(uniform, 1,(GLfloat*)val);
704                 else if (len == 3)
705                         glUniform3fvARB(uniform, 1,(GLfloat*)val);
706                 else if (len == 4)
707                         glUniform4fvARB(uniform, 1,(GLfloat*)val);
708                 else
709                         MT_assert(0);
710         }
711 }
712
713 void BL_Shader::SetUniform(int uniform, const int* val, int len)
714 {
715         if( GLEW_ARB_fragment_shader &&
716                 GLEW_ARB_vertex_shader &&
717                 GLEW_ARB_shader_objects 
718                 )
719         {
720                 if(len == 2) 
721                         glUniform2ivARB(uniform, 1, (GLint*)val);
722                 else if (len == 3)
723                         glUniform3ivARB(uniform, 1, (GLint*)val);
724                 else if (len == 4)
725                         glUniform4ivARB(uniform, 1, (GLint*)val);
726                 else
727                         MT_assert(0);
728         }
729 }
730
731
732 PyObject* BL_Shader::py_getattro(PyObject *attr)
733 {
734         py_getattro_up(PyObjectPlus);
735 }
736
737 PyObject* BL_Shader::py_getattro_dict() {
738         py_getattro_dict_up(PyObjectPlus);
739 }
740
741
742 PyMethodDef BL_Shader::Methods[] = 
743 {
744         // creation
745         KX_PYMETHODTABLE( BL_Shader, setSource ),
746         KX_PYMETHODTABLE( BL_Shader, delSource ),
747         KX_PYMETHODTABLE( BL_Shader, getVertexProg ),
748         KX_PYMETHODTABLE( BL_Shader, getFragmentProg ),
749         KX_PYMETHODTABLE( BL_Shader, setNumberOfPasses ),
750         KX_PYMETHODTABLE( BL_Shader, validate),
751         /// access functions
752         KX_PYMETHODTABLE( BL_Shader, isValid),
753         KX_PYMETHODTABLE( BL_Shader, setUniform1f ),
754         KX_PYMETHODTABLE( BL_Shader, setUniform2f ),
755         KX_PYMETHODTABLE( BL_Shader, setUniform3f ),
756         KX_PYMETHODTABLE( BL_Shader, setUniform4f ),
757         KX_PYMETHODTABLE( BL_Shader, setUniform1i ),
758         KX_PYMETHODTABLE( BL_Shader, setUniform2i ),
759         KX_PYMETHODTABLE( BL_Shader, setUniform3i ),
760         KX_PYMETHODTABLE( BL_Shader, setUniform4i ),
761         KX_PYMETHODTABLE( BL_Shader, setAttrib ),
762
763         KX_PYMETHODTABLE( BL_Shader, setUniformfv ),
764         KX_PYMETHODTABLE( BL_Shader, setUniformiv ),
765         KX_PYMETHODTABLE( BL_Shader, setUniformDef ),
766
767         KX_PYMETHODTABLE( BL_Shader, setSampler  ),
768         KX_PYMETHODTABLE( BL_Shader, setUniformMatrix4 ),
769         KX_PYMETHODTABLE( BL_Shader, setUniformMatrix3 ),
770
771         {NULL,NULL} //Sentinel
772 };
773
774 PyAttributeDef BL_Shader::Attributes[] = {
775         { NULL }        //Sentinel
776 };
777
778 PyTypeObject BL_Shader::Type = {
779 #if (PY_VERSION_HEX >= 0x02060000)
780         PyVarObject_HEAD_INIT(NULL, 0)
781 #else
782         /* python 2.5 and below */
783         PyObject_HEAD_INIT( NULL )  /* required py macro */
784         0,                          /* ob_size */
785 #endif
786                 "BL_Shader",
787                 sizeof(PyObjectPlus_Proxy),
788                 0,
789                 py_base_dealloc,
790                 0,
791                 0,
792                 0,
793                 0,
794                 py_base_repr,
795                 0,0,0,0,0,0,
796                 py_base_getattro,
797                 py_base_setattro,
798                 0,0,0,0,0,0,0,0,0,
799                 Methods
800 };
801
802
803 PyParentObject BL_Shader::Parents[] = {
804         &BL_Shader::Type,
805         &PyObjectPlus::Type,
806         NULL
807 };
808
809
810 KX_PYMETHODDEF_DOC( BL_Shader, setSource," setSource(vertexProgram, fragmentProgram)" )
811 {
812         if(mShader !=0 && mOk  )
813         {
814                 // already set...
815                 Py_RETURN_NONE;
816         }
817         char *v,*f;
818         int apply=0;
819         if( PyArg_ParseTuple(args, "ssi:setSource", &v, &f, &apply) )
820         {
821                 vertProg = v;
822                 fragProg = f;
823                 if( LinkProgram() ) {
824                         glUseProgramObjectARB( mShader );
825                         mUse = apply!=0;
826                         Py_RETURN_NONE;
827                 }
828                 vertProg = 0;
829                 fragProg = 0;
830                 mUse = 0;
831                 Py_RETURN_NONE;
832         }
833         return NULL;
834 }
835
836
837 KX_PYMETHODDEF_DOC( BL_Shader, delSource, "delSource( )" )
838 {
839         ClearUniforms();
840         glUseProgramObjectARB(0);
841
842         glDeleteObjectARB(mShader);
843         mShader         = 0;
844         mOk                     = 0;
845         mUse            = 0;
846         Py_RETURN_NONE;
847 }
848
849 KX_PYMETHODDEF_DOC( BL_Shader, isValid, "isValid()" )
850 {
851         return PyInt_FromLong( ( mShader !=0 &&  mOk ) );
852 }
853
854 KX_PYMETHODDEF_DOC( BL_Shader, getVertexProg ,"getVertexProg( )" )
855 {
856         return PyString_FromString(vertProg?vertProg:"");
857 }
858
859 KX_PYMETHODDEF_DOC( BL_Shader, getFragmentProg ,"getFragmentProg( )" )
860 {
861         return PyString_FromString(fragProg?fragProg:"");
862 }
863
864 KX_PYMETHODDEF_DOC( BL_Shader, validate, "validate()")
865 {
866         if(mError) {
867                 Py_RETURN_NONE;
868         }
869         if(mShader==0) {
870                 PyErr_SetString(PyExc_TypeError, "shader.validate(): BL_Shader, invalid shader object");
871                 return NULL;
872         }
873         int stat = 0;
874         glValidateProgramARB(mShader);
875         glGetObjectParameterivARB(mShader, GL_OBJECT_VALIDATE_STATUS_ARB,(GLint*) &stat);
876
877
878         if(stat > 0 && stat < MAX_LOG_LEN) {
879                 int char_len=0;
880                 char *logInf = (char*)MEM_mallocN(stat, "validate-log");
881
882                 glGetInfoLogARB(mShader, stat,(GLsizei*) &char_len, logInf);
883                 if(char_len >0) {
884                         spit("---- GLSL Validation ----");
885                         spit(logInf);
886                 }
887                 MEM_freeN(logInf);
888                 logInf=0;
889         }
890         Py_RETURN_NONE;
891 }
892
893
894 KX_PYMETHODDEF_DOC( BL_Shader, setSampler, "setSampler(name, index)" )
895 {
896         if(mError) {
897                 Py_RETURN_NONE;
898         }
899
900         const char *uniform="";
901         int index=-1;
902         if(PyArg_ParseTuple(args, "si:setSampler", &uniform, &index)) 
903         {
904                 int loc = GetUniformLocation(uniform);
905                 if(loc != -1) {
906                         if(index >= MAXTEX &&  index < 0)
907                                 spit("Invalid texture sample index: " << index);
908
909 #ifdef SORT_UNIFORMS
910                         SetUniformiv(loc, BL_Uniform::UNI_INT, &index, (sizeof(int)) );
911 #else
912                         SetUniform(loc, index);
913 #endif
914                         //if(index <= MAXTEX)
915                         //      mSampler[index].mLoc = loc;
916                         //else
917                         //      spit("Invalid texture sample index: " << index);
918                 }
919                 Py_RETURN_NONE;
920         }
921         return NULL;
922 }
923
924 KX_PYMETHODDEF_DOC( BL_Shader, setNumberOfPasses, "setNumberOfPasses( max-pass )" )
925 {
926         int pass = 1;
927         if(!PyArg_ParseTuple(args, "i:setNumberOfPasses", &pass))
928                 return NULL;
929
930         mPass = 1;
931         Py_RETURN_NONE;
932 }
933
934 /// access functions
935 KX_PYMETHODDEF_DOC( BL_Shader, setUniform1f, "setUniform1f(name, fx)" )
936 {
937         if(mError) {
938                 Py_RETURN_NONE;
939         }
940
941         const char *uniform="";
942         float value=0;
943         if(PyArg_ParseTuple(args, "sf:setUniform1f", &uniform, &value ))
944         {
945                 int loc = GetUniformLocation(uniform);
946                 if(loc != -1)
947                 {
948 #ifdef SORT_UNIFORMS
949                         SetUniformfv(loc, BL_Uniform::UNI_FLOAT, &value, sizeof(float));
950 #else                   
951                         SetUniform( loc, (float)value );
952 #endif
953                 }
954                 Py_RETURN_NONE;
955         }
956         return NULL;
957 }
958
959
960 KX_PYMETHODDEF_DOC( BL_Shader, setUniform2f , "setUniform2f(name, fx, fy)")
961 {
962         if(mError) {
963                 Py_RETURN_NONE;
964         }
965         const char *uniform="";
966         float array[2]={ 0,0 };
967         if(PyArg_ParseTuple(args, "sff:setUniform2f", &uniform, &array[0],&array[1] ))
968         {
969                 int loc = GetUniformLocation(uniform);
970                 if(loc != -1)
971                 {
972 #ifdef SORT_UNIFORMS
973                         SetUniformfv(loc, BL_Uniform::UNI_FLOAT2, array, (sizeof(float)*2) );
974 #else
975                         SetUniform(loc, array, 2);
976 #endif
977                 }
978                 Py_RETURN_NONE;
979         }
980         return NULL;
981 }
982
983
984 KX_PYMETHODDEF_DOC( BL_Shader, setUniform3f, "setUniform3f(name, fx,fy,fz) ")
985 {
986         if(mError) {
987                 Py_RETURN_NONE;
988         }
989         const char *uniform="";
990         float array[3]={0,0,0};
991         if(PyArg_ParseTuple(args, "sfff:setUniform3f", &uniform, &array[0],&array[1],&array[2]))
992         {
993                 int loc = GetUniformLocation(uniform);
994                 if(loc != -1)
995                 {
996 #ifdef SORT_UNIFORMS
997                         SetUniformfv(loc, BL_Uniform::UNI_FLOAT3, array, (sizeof(float)*3) );
998 #else
999                         SetUniform(loc, array, 3);
1000 #endif
1001                 }
1002                 Py_RETURN_NONE;
1003
1004         }
1005         return NULL;
1006 }
1007
1008
1009 KX_PYMETHODDEF_DOC( BL_Shader, setUniform4f, "setUniform4f(name, fx,fy,fz, fw) ")
1010 {
1011         if(mError) {
1012                 Py_RETURN_NONE;
1013         }
1014         const char *uniform="";
1015         float array[4]={0,0,0,0};
1016         if(PyArg_ParseTuple(args, "sffff:setUniform4f", &uniform, &array[0],&array[1],&array[2], &array[3]))
1017         {
1018                 int loc = GetUniformLocation(uniform);
1019                 if(loc != -1)
1020                 {
1021 #ifdef SORT_UNIFORMS
1022                         SetUniformfv(loc, BL_Uniform::UNI_FLOAT4, array, (sizeof(float)*4) );
1023 #else
1024                         SetUniform(loc, array, 4);
1025 #endif
1026                 }
1027                 Py_RETURN_NONE;
1028         }
1029         return NULL;
1030 }
1031
1032
1033 KX_PYMETHODDEF_DOC( BL_Shader, setUniform1i, "setUniform1i(name, ix)" )
1034 {
1035         if(mError) {
1036                 Py_RETURN_NONE;
1037         }
1038         const char *uniform="";
1039         int value=0;
1040         if(PyArg_ParseTuple(args, "si:setUniform1i", &uniform, &value ))
1041         {
1042                 int loc = GetUniformLocation(uniform);
1043                 if(loc != -1)
1044                 {
1045 #ifdef SORT_UNIFORMS
1046                         SetUniformiv(loc, BL_Uniform::UNI_INT, &value, sizeof(int));
1047 #else
1048                         SetUniform(loc, (int)value);
1049 #endif
1050                 }
1051                 Py_RETURN_NONE;
1052         }
1053         return NULL;
1054 }
1055
1056
1057 KX_PYMETHODDEF_DOC( BL_Shader, setUniform2i , "setUniform2i(name, ix, iy)")
1058 {
1059         if(mError) {
1060                 Py_RETURN_NONE;
1061         }
1062         const char *uniform="";
1063         int array[2]={ 0,0 };
1064         if(PyArg_ParseTuple(args, "sii:setUniform2i", &uniform, &array[0],&array[1] ))
1065         {
1066                 int loc = GetUniformLocation(uniform);
1067                 if(loc != -1)
1068                 {
1069 #ifdef SORT_UNIFORMS
1070                         SetUniformiv(loc, BL_Uniform::UNI_INT2, array, sizeof(int)*2);
1071 #else
1072                         SetUniform(loc, array, 2);
1073 #endif
1074                 }
1075                 Py_RETURN_NONE;
1076         }
1077         return NULL;
1078 }
1079
1080
1081 KX_PYMETHODDEF_DOC( BL_Shader, setUniform3i, "setUniform3i(name, ix,iy,iz) ")
1082 {
1083         if(mError) {
1084                 Py_RETURN_NONE;
1085         }
1086
1087         const char *uniform="";
1088         int array[3]={0,0,0};
1089         if(PyArg_ParseTuple(args, "siii:setUniform3i", &uniform, &array[0],&array[1],&array[2]))
1090         {
1091                 int loc = GetUniformLocation(uniform);
1092                 if(loc != -1)
1093                 {
1094 #ifdef SORT_UNIFORMS
1095                         SetUniformiv(loc, BL_Uniform::UNI_INT3, array, sizeof(int)*3);
1096 #else
1097                         SetUniform(loc, array, 3);
1098 #endif
1099                 }
1100                 Py_RETURN_NONE;
1101         }
1102         return NULL;
1103 }
1104
1105 KX_PYMETHODDEF_DOC( BL_Shader, setUniform4i, "setUniform4i(name, ix,iy,iz, iw) ")
1106 {
1107         if(mError) {
1108                 Py_RETURN_NONE;
1109         }
1110         const char *uniform="";
1111         int array[4]={0,0,0, 0};
1112         if(PyArg_ParseTuple(args, "siiii:setUniform4i", &uniform, &array[0],&array[1],&array[2], &array[3] ))
1113         {
1114                 int loc = GetUniformLocation(uniform);
1115                 if(loc != -1)
1116                 {
1117 #ifdef SORT_UNIFORMS
1118                         SetUniformiv(loc, BL_Uniform::UNI_INT4, array, sizeof(int)*4);
1119 #else
1120                         SetUniform(loc, array, 4);
1121 #endif
1122                 }
1123                 Py_RETURN_NONE;
1124         }
1125         return NULL;
1126 }
1127
1128 KX_PYMETHODDEF_DOC( BL_Shader, setUniformfv , "setUniformfv( float (list2 or list3 or list4) )")
1129 {
1130         if(mError) {
1131                 Py_RETURN_NONE;
1132         }
1133         const char *uniform = "";
1134         PyObject *listPtr =0;
1135         float array_data[4] = {0.f,0.f,0.f,0.f};
1136
1137         if(PyArg_ParseTuple(args, "sO:setUniformfv", &uniform, &listPtr))
1138         {
1139                 int loc = GetUniformLocation(uniform);
1140                 if(loc != -1)
1141                 {
1142                         if(PySequence_Check(listPtr))
1143                         {
1144                                 unsigned int list_size = PySequence_Size(listPtr);
1145                                 
1146                                 for(unsigned int i=0; (i<list_size && i<4); i++)
1147                                 {
1148                                         PyObject *item = PySequence_GetItem(listPtr, i);
1149                                         array_data[i] = (float)PyFloat_AsDouble(item);
1150                                         Py_DECREF(item);
1151                                 }
1152
1153                                 switch(list_size)
1154                                 {
1155                                 case 2:
1156                                         {
1157                                                 float array2[2] = { array_data[0],array_data[1] };
1158 #ifdef SORT_UNIFORMS
1159                                                 SetUniformfv(loc, BL_Uniform::UNI_FLOAT2, array2, sizeof(float)*2);
1160 #else
1161                                                 SetUniform(loc, array2, 2);                                             
1162 #endif
1163                                                 Py_RETURN_NONE;
1164                                         } break;
1165                                 case 3:
1166                                         {
1167                                                 float array3[3] = { array_data[0],array_data[1],array_data[2] };
1168 #ifdef SORT_UNIFORMS
1169                                                 SetUniformfv(loc, BL_Uniform::UNI_FLOAT3, array3, sizeof(float)*3);
1170 #else
1171                                                 SetUniform(loc, array3, 3);     
1172 #endif
1173                                                 Py_RETURN_NONE;
1174                                         }break;
1175                                 case 4:
1176                                         {
1177                                                 float array4[4] = { array_data[0],array_data[1],array_data[2],array_data[3] };
1178 #ifdef SORT_UNIFORMS
1179                                                 SetUniformfv(loc, BL_Uniform::UNI_FLOAT4, array4, sizeof(float)*4);
1180 #else
1181                                                 SetUniform(loc, array4, 4);     
1182 #endif
1183                                                 Py_RETURN_NONE;
1184                                         }break;
1185                                 default:
1186                                         {
1187                                                 PyErr_SetString(PyExc_TypeError, "shader.setUniform4i(name, ix,iy,iz, iw): BL_Shader. invalid list size");
1188                                                 return NULL;
1189                                         }break;
1190                                 }
1191                         }
1192                 }
1193         }
1194         return NULL;
1195 }
1196
1197 KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( uniform_name, (list2 or list3 or list4) )")
1198 {
1199         if(mError) {
1200                 Py_RETURN_NONE;
1201         }
1202         const char *uniform = "";
1203         PyObject *listPtr =0;
1204         int array_data[4] = {0,0,0,0};
1205
1206         if(!PyArg_ParseTuple(args, "sO:setUniformiv", &uniform, &listPtr))
1207                 return NULL;
1208         
1209         int loc = GetUniformLocation(uniform);
1210         
1211         if(loc == -1) {
1212                 PyErr_SetString(PyExc_TypeError, "shader.setUniformiv(...): BL_Shader, first string argument is not a valid uniform value");
1213                 return NULL;
1214         }
1215         
1216         if(!PySequence_Check(listPtr)) {
1217                 PyErr_SetString(PyExc_TypeError, "shader.setUniformiv(...): BL_Shader, second argument is not a sequence");
1218                 return NULL;
1219         }
1220         
1221         unsigned int list_size = PySequence_Size(listPtr);
1222         
1223         for(unsigned int i=0; (i<list_size && i<4); i++)
1224         {
1225                 PyObject *item = PySequence_GetItem(listPtr, i);
1226                 array_data[i] = PyInt_AsLong(item);
1227                 Py_DECREF(item);
1228         }
1229         
1230         if(PyErr_Occurred()) {
1231                 PyErr_SetString(PyExc_TypeError, "shader.setUniformiv(...): BL_Shader, one or more values in the list is not an int");
1232                 return NULL;
1233         }
1234         
1235         /* Sanity checks done! */
1236         
1237         switch(list_size)
1238         {
1239         case 2:
1240                 {
1241                         int array2[2] = { array_data[0],array_data[1]};
1242 #ifdef SORT_UNIFORMS
1243                         SetUniformiv(loc, BL_Uniform::UNI_INT2, array2, sizeof(int)*2);
1244 #else
1245                         SetUniform(loc, array2, 2);                                             
1246 #endif
1247                         Py_RETURN_NONE;
1248                 } break;
1249         case 3:
1250                 {
1251                         int array3[3] = { array_data[0],array_data[1],array_data[2] };
1252 #ifdef SORT_UNIFORMS
1253                         SetUniformiv(loc, BL_Uniform::UNI_INT3, array3, sizeof(int)*3);
1254                         
1255 #else
1256                         SetUniform(loc, array3, 3);     
1257 #endif
1258                         Py_RETURN_NONE;
1259                 }break;
1260         case 4:
1261                 {
1262                         int array4[4] = { array_data[0],array_data[1],array_data[2],array_data[3] };
1263 #ifdef SORT_UNIFORMS
1264                         SetUniformiv(loc, BL_Uniform::UNI_INT4, array4, sizeof(int)*4);
1265                         
1266 #else
1267                         SetUniform(loc, array4, 4);     
1268 #endif
1269                         Py_RETURN_NONE;
1270                 }break;
1271         default:
1272                 {
1273                         PyErr_SetString(PyExc_TypeError, "shader.setUniformiv(...): BL_Shader, second argument, invalid list size, expected an int list between 2 and 4");
1274                         return NULL;
1275                 }break;
1276         }
1277         
1278         Py_RETURN_NONE;
1279 }
1280
1281
1282 KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix4, 
1283 "setUniformMatrix4(uniform_name, mat-4x4, transpose(row-major=true, col-major=false)" )
1284 {
1285         if(mError) {
1286                 Py_RETURN_NONE;
1287         }
1288
1289         float matr[16] = {
1290                 1,0,0,0,
1291                 0,1,0,0,
1292                 0,0,1,0,
1293                 0,0,0,1
1294         };
1295
1296         const char *uniform="";
1297         PyObject *matrix=0;
1298         int transp=1; // MT_ is row major so transpose by default....
1299         
1300         if(!PyArg_ParseTuple(args, "sO|i:setUniformMatrix4",&uniform, &matrix,&transp))
1301                 return NULL;
1302
1303         int loc = GetUniformLocation(uniform);
1304         
1305         if(loc == -1) {
1306                 PyErr_SetString(PyExc_TypeError, "shader.setUniformMatrix4(...): BL_Shader, first string argument is not a valid uniform value");
1307                 return NULL;
1308         }
1309         
1310         MT_Matrix4x4 mat;
1311         
1312         if (!PyMatTo(matrix, mat)) {
1313                 PyErr_SetString(PyExc_TypeError, "shader.setUniformMatrix4(...): BL_Shader, second argument cannot be converted into a 4x4 matrix");
1314                 return NULL;
1315         }
1316         
1317         /* Sanity checks done! */
1318
1319 #ifdef SORT_UNIFORMS
1320         mat.getValue(matr);
1321         SetUniformfv(loc, BL_Uniform::UNI_MAT4, matr, (sizeof(float)*16), (transp!=0) );
1322 #else
1323         SetUniform(loc,mat,(transp!=0));
1324 #endif
1325         Py_RETURN_NONE;
1326 }
1327
1328
1329 KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix3,
1330 "setUniformMatrix3(uniform_name, list[3x3], transpose(row-major=true, col-major=false)" )
1331 {
1332         if(mError) {
1333                 Py_RETURN_NONE;
1334         }
1335
1336         float matr[9] = {
1337                 1,0,0,
1338                 0,1,0,
1339                 0,0,1,
1340         };
1341
1342         const char *uniform="";
1343         PyObject *matrix=0;
1344         int transp=1; // MT_ is row major so transpose by default....
1345         if(!PyArg_ParseTuple(args, "sO|i:setUniformMatrix3",&uniform, &matrix,&transp))
1346                 return NULL;
1347         
1348         int loc = GetUniformLocation(uniform);
1349         
1350         if(loc == -1) {
1351                 PyErr_SetString(PyExc_TypeError, "shader.setUniformMatrix3(...): BL_Shader, first string argument is not a valid uniform value");
1352                 return NULL;
1353         }
1354         
1355         
1356         MT_Matrix3x3 mat;
1357         
1358         if (!PyMatTo(matrix, mat)) {
1359                 PyErr_SetString(PyExc_TypeError, "shader.setUniformMatrix3(...): BL_Shader, second argument cannot be converted into a 3x3 matrix");
1360                 return NULL;
1361         }
1362         
1363
1364 #ifdef SORT_UNIFORMS
1365         mat.getValue(matr);
1366         SetUniformfv(loc, BL_Uniform::UNI_MAT3, matr, (sizeof(float)*9), (transp!=0) );
1367 #else
1368         SetUniform(loc,mat,(transp!=0));
1369 #endif
1370         Py_RETURN_NONE;
1371 }
1372
1373 KX_PYMETHODDEF_DOC( BL_Shader, setAttrib, "setAttrib(enum)" )
1374 {
1375         if(mError) {
1376                 Py_RETURN_NONE;
1377         }
1378         
1379         int attr=0;
1380         
1381         if(!PyArg_ParseTuple(args, "i:setAttrib", &attr ))
1382                 return NULL;
1383         
1384         if(mShader==0) {
1385                 PyErr_SetString(PyExc_ValueError, "shader.setAttrib() BL_Shader, invalid shader object");
1386                 return NULL;
1387         }
1388         mAttr=SHD_TANGENT; /* What the heck is going on here - attr is just ignored??? - Campbell */
1389         glUseProgramObjectARB(mShader);
1390         glBindAttribLocationARB(mShader, mAttr, "Tangent");
1391         Py_RETURN_NONE;
1392 }
1393
1394
1395 KX_PYMETHODDEF_DOC( BL_Shader, setUniformDef, "setUniformDef(name, enum)" )
1396 {
1397         if(mError) {
1398                 Py_RETURN_NONE;
1399         }
1400
1401         const char *uniform="";
1402         int nloc=0;
1403         if(PyArg_ParseTuple(args, "si:setUniformDef",&uniform, &nloc))
1404         {
1405                 int loc = GetUniformLocation(uniform);
1406                 if(loc != -1)
1407                 {
1408                         bool defined = false;
1409                         BL_UniformVecDef::iterator it = mPreDef.begin();
1410                         while(it != mPreDef.end()) {
1411                                 if((*it)->mLoc == loc) {
1412                                         defined = true;
1413                                         break;
1414                                 }
1415                                 it++;
1416                         }
1417                         if(defined)
1418                         {
1419                                 Py_RETURN_NONE;
1420                         }
1421
1422                         BL_DefUniform *uni = new BL_DefUniform();
1423                         uni->mLoc = loc;
1424                         uni->mType = nloc;
1425                         uni->mFlag = 0;
1426                         mPreDef.push_back(uni);
1427                         Py_RETURN_NONE;
1428                 }
1429         }
1430         return NULL;
1431 }
1432
1433 // eof