renaming BooleanProperty to BoolProperty (rna structs shouldnt affect scripters)
[blender-staging.git] / source / blender / editors / space_view3d / drawmesh.c
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  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation, full update, glsl support
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/space_view3d/drawmesh.c
27  *  \ingroup spview3d
28  */
29
30 #include <string.h>
31 #include <math.h>
32
33 #include "MEM_guardedalloc.h"
34
35 #include "BLI_blenlib.h"
36 #include "BLI_math.h"
37 #include "BLI_edgehash.h"
38 #include "BLI_editVert.h"
39 #include "BLI_utildefines.h"
40
41 #include "DNA_material_types.h"
42 #include "DNA_meshdata_types.h"
43 #include "DNA_node_types.h"
44 #include "DNA_object_types.h"
45 #include "DNA_property_types.h"
46 #include "DNA_scene_types.h"
47 #include "DNA_screen_types.h"
48 #include "DNA_view3d_types.h"
49
50 #include "BKE_DerivedMesh.h"
51 #include "BKE_effect.h"
52 #include "BKE_image.h"
53 #include "BKE_material.h"
54 #include "BKE_paint.h"
55 #include "BKE_property.h"
56 #include "BKE_scene.h"
57
58 #include "BIF_gl.h"
59 #include "BIF_glutil.h"
60
61 #include "UI_resources.h"
62
63 #include "GPU_buffers.h"
64 #include "GPU_extensions.h"
65 #include "GPU_draw.h"
66 #include "GPU_material.h"
67
68 #include "ED_mesh.h"
69 #include "ED_uvedit.h"
70
71 #include "view3d_intern.h"      // own include
72
73 /**************************** Face Select Mode *******************************/
74
75 /* Flags for marked edges */
76 enum {
77         eEdge_Visible = (1<<0),
78         eEdge_Select = (1<<1),
79 };
80
81 /* Creates a hash of edges to flags indicating selected/visible */
82 static void get_marked_edge_info__orFlags(EdgeHash *eh, int v0, int v1, int flags)
83 {
84         int *flags_p;
85
86         if(!BLI_edgehash_haskey(eh, v0, v1))
87                 BLI_edgehash_insert(eh, v0, v1, NULL);
88
89         flags_p = (int*) BLI_edgehash_lookup_p(eh, v0, v1);
90         *flags_p |= flags;
91 }
92
93 static EdgeHash *get_tface_mesh_marked_edge_info(Mesh *me)
94 {
95         EdgeHash *eh = BLI_edgehash_new();
96         MFace *mf;
97         int i;
98         
99         for(i=0; i<me->totface; i++) {
100                 mf = &me->mface[i];
101
102                 if(!(mf->flag & ME_HIDE)) {
103                         unsigned int flags = eEdge_Visible;
104                         if(mf->flag & ME_FACE_SEL) flags |= eEdge_Select;
105
106                         get_marked_edge_info__orFlags(eh, mf->v1, mf->v2, flags);
107                         get_marked_edge_info__orFlags(eh, mf->v2, mf->v3, flags);
108
109                         if(mf->v4) {
110                                 get_marked_edge_info__orFlags(eh, mf->v3, mf->v4, flags);
111                                 get_marked_edge_info__orFlags(eh, mf->v4, mf->v1, flags);
112                         }
113                         else
114                                 get_marked_edge_info__orFlags(eh, mf->v3, mf->v1, flags);
115                 }
116         }
117
118         return eh;
119 }
120
121
122 static int draw_mesh_face_select__setHiddenOpts(void *userData, int index)
123 {
124         struct { Mesh *me; EdgeHash *eh; } *data = userData;
125         Mesh *me= data->me;
126         MEdge *med = &me->medge[index];
127         uintptr_t flags = (intptr_t) BLI_edgehash_lookup(data->eh, med->v1, med->v2);
128
129         if(me->drawflag & ME_DRAWEDGES) { 
130                 if(me->drawflag & ME_HIDDENEDGES)
131                         return 1;
132                 else
133                         return (flags & eEdge_Visible);
134         }
135         else
136                 return (flags & eEdge_Select);
137 }
138
139 static int draw_mesh_face_select__setSelectOpts(void *userData, int index)
140 {
141         struct { Mesh *me; EdgeHash *eh; } *data = userData;
142         MEdge *med = &data->me->medge[index];
143         uintptr_t flags = (intptr_t) BLI_edgehash_lookup(data->eh, med->v1, med->v2);
144
145         return flags & eEdge_Select;
146 }
147
148 /* draws unselected */
149 static int draw_mesh_face_select__drawFaceOptsInv(void *userData, int index)
150 {
151         Mesh *me = (Mesh*)userData;
152
153         MFace *mface = &me->mface[index];
154         if(!(mface->flag&ME_HIDE) && !(mface->flag&ME_FACE_SEL))
155                 return 2; /* Don't set color */
156         else
157                 return 0;
158 }
159
160 static void draw_mesh_face_select(RegionView3D *rv3d, Mesh *me, DerivedMesh *dm)
161 {
162         struct { Mesh *me; EdgeHash *eh; } data;
163
164         data.me = me;
165         data.eh = get_tface_mesh_marked_edge_info(me);
166
167         glEnable(GL_DEPTH_TEST);
168         glDisable(GL_LIGHTING);
169         bglPolygonOffset(rv3d->dist, 1.0);
170
171         /* Draw (Hidden) Edges */
172         setlinestyle(1);
173         UI_ThemeColor(TH_EDGE_FACESEL);
174         dm->drawMappedEdges(dm, draw_mesh_face_select__setHiddenOpts, &data);
175         setlinestyle(0);
176
177         /* Draw Selected Faces */
178         if(me->drawflag & ME_DRAWFACES) {
179                 glEnable(GL_BLEND);
180                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
181                 /* dull unselected faces so as not to get in the way of seeing color */
182                 glColor4ub(96, 96, 96, 64);
183                 dm->drawMappedFacesTex(dm, draw_mesh_face_select__drawFaceOptsInv, NULL, (void*)me);
184                 
185                 glDisable(GL_BLEND);
186         }
187         
188         bglPolygonOffset(rv3d->dist, 1.0);
189
190                 /* Draw Stippled Outline for selected faces */
191         glColor3ub(255, 255, 255);
192         setlinestyle(1);
193         dm->drawMappedEdges(dm, draw_mesh_face_select__setSelectOpts, &data);
194         setlinestyle(0);
195
196         bglPolygonOffset(rv3d->dist, 0.0);      // resets correctly now, even after calling accumulated offsets
197
198         BLI_edgehash_free(data.eh, NULL);
199 }
200
201 /***************************** Texture Drawing ******************************/
202
203 static Material *give_current_material_or_def(Object *ob, int matnr)
204 {
205         extern Material defmaterial;    // render module abuse...
206         Material *ma= give_current_material(ob, matnr);
207
208         return ma?ma:&defmaterial;
209 }
210
211 /* Icky globals, fix with userdata parameter */
212
213 static struct TextureDrawState {
214         Object *ob;
215         int islit, istex;
216         int color_profile;
217         unsigned char obcol[4];
218 } Gtexdraw = {NULL, 0, 0, 0, {0, 0, 0, 0}};
219
220 static int set_draw_settings_cached(int clearcache, MTFace *texface, Material *ma, struct TextureDrawState gtexdraw)
221 {
222         static Material *c_ma;
223         static int c_textured;
224         static MTFace *c_texface;
225         static int c_backculled;
226         static int c_badtex;
227         static int c_lit;
228
229         Object *litob = NULL; //to get mode to turn off mipmap in painting mode
230         int backculled = GEMAT_BACKCULL;
231         int alphablend = 0;
232         int textured = 0;
233         int lit = 0;
234         
235         if (clearcache) {
236                 c_textured= c_lit= c_backculled= -1;
237                 c_texface= (MTFace*) -1;
238                 c_badtex= 0;
239         } else {
240                 textured = gtexdraw.istex;
241                 litob = gtexdraw.ob;
242         }
243
244         /* convert number of lights into boolean */
245         if (gtexdraw.islit) lit = 1;
246
247         if (ma) {
248                 alphablend = ma->game.alpha_blend;
249                 if (ma->mode & MA_SHLESS) lit = 0;
250                 backculled = ma->game.flag & GEMAT_BACKCULL;
251         }
252
253         if (texface) {
254                 textured = textured && (texface->tpage);
255
256                 /* no material, render alpha if texture has depth=32 */
257                 if (!ma && BKE_image_has_alpha(texface->tpage))
258                         alphablend = GPU_BLEND_ALPHA;
259         }
260
261         else
262                 textured = 0;
263
264         if (backculled!=c_backculled) {
265                 if (backculled) glEnable(GL_CULL_FACE);
266                 else glDisable(GL_CULL_FACE);
267
268                 c_backculled= backculled;
269         }
270
271         if (textured!=c_textured || texface!=c_texface) {
272                 if (textured ) {
273                         c_badtex= !GPU_set_tpage(texface, !(litob->mode & OB_MODE_TEXTURE_PAINT), alphablend);
274                 } else {
275                         GPU_set_tpage(NULL, 0, 0);
276                         c_badtex= 0;
277                 }
278                 c_textured= textured;
279                 c_texface= texface;
280         }
281
282         if (c_badtex) lit= 0;
283         if (lit!=c_lit || ma!=c_ma) {
284                 if (lit) {
285                         float spec[4];
286                         if (!ma)ma= give_current_material_or_def(NULL, 0); //default material
287
288                         spec[0]= ma->spec*ma->specr;
289                         spec[1]= ma->spec*ma->specg;
290                         spec[2]= ma->spec*ma->specb;
291                         spec[3]= 1.0;
292
293                         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec);
294                         glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
295                         glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, CLAMPIS(ma->har, 0, 128));
296                         glEnable(GL_LIGHTING);
297                         glEnable(GL_COLOR_MATERIAL);
298                 }
299                 else {
300                         glDisable(GL_LIGHTING); 
301                         glDisable(GL_COLOR_MATERIAL);
302                 }
303                 c_lit= lit;
304         }
305
306         return c_badtex;
307 }
308
309 static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob)
310 {
311         unsigned char obcol[4];
312         int istex, solidtex;
313
314         // XXX scene->obedit warning
315
316         /* texture draw is abused for mask selection mode, do this so wire draw
317          * with face selection in weight paint is not lit. */
318         if((v3d->drawtype <= OB_WIRE) && (ob->mode & OB_MODE_WEIGHT_PAINT)) {
319                 solidtex= FALSE;
320                 Gtexdraw.islit= 0;
321         }
322         else if(v3d->drawtype==OB_SOLID || ((ob->mode & OB_MODE_EDIT) && v3d->drawtype!=OB_TEXTURE)) {
323                 /* draw with default lights in solid draw mode and edit mode */
324                 solidtex= TRUE;
325                 Gtexdraw.islit= -1;
326         }
327         else {
328                 /* draw with lights in the scene otherwise */
329                 solidtex= FALSE;
330                 Gtexdraw.islit= GPU_scene_object_lights(scene, ob, v3d->lay, rv3d->viewmat, !rv3d->is_persp);
331         }
332         
333         obcol[0]= CLAMPIS(ob->col[0]*255, 0, 255);
334         obcol[1]= CLAMPIS(ob->col[1]*255, 0, 255);
335         obcol[2]= CLAMPIS(ob->col[2]*255, 0, 255);
336         obcol[3]= CLAMPIS(ob->col[3]*255, 0, 255);
337         
338         glCullFace(GL_BACK); glEnable(GL_CULL_FACE);
339         if(solidtex || v3d->drawtype==OB_TEXTURE) istex= 1;
340         else istex= 0;
341
342         Gtexdraw.ob = ob;
343         Gtexdraw.istex = istex;
344         Gtexdraw.color_profile = scene->r.color_mgt_flag & R_COLOR_MANAGEMENT;
345         memcpy(Gtexdraw.obcol, obcol, sizeof(obcol));
346         set_draw_settings_cached(1, NULL, NULL, Gtexdraw);
347         glShadeModel(GL_SMOOTH);
348 }
349
350 static void draw_textured_end(void)
351 {
352         /* switch off textures */
353         GPU_set_tpage(NULL, 0, 0);
354
355         glShadeModel(GL_FLAT);
356         glDisable(GL_CULL_FACE);
357
358         /* XXX, bad patch - GPU_default_lights() calls
359          * glLightfv(GL_LIGHT_POSITION, ...) which
360          * is transformed by the current matrix... we
361          * need to make sure that matrix is identity.
362          * 
363          * It would be better if drawmesh.c kept track
364          * of and restored the light settings it changed.
365          *  - zr
366          */
367         glPushMatrix();
368         glLoadIdentity();       
369         GPU_default_lights();
370         glPopMatrix();
371 }
372
373 static int draw_tface__set_draw_legacy(MTFace *tface, int has_mcol, int matnr)
374 {
375         Material *ma= give_current_material(Gtexdraw.ob, matnr+1);
376         int validtexture=0;
377
378         if (ma && (ma->game.flag & GEMAT_INVISIBLE)) return 0;
379
380         validtexture = set_draw_settings_cached(0, tface, ma, Gtexdraw);
381
382         if (tface && validtexture) {
383                 glColor3ub(0xFF, 0x00, 0xFF);
384                 return 2; /* Don't set color */
385         } else if (ma && ma->shade_flag&MA_OBCOLOR) {
386                 glColor3ubv(Gtexdraw.obcol);
387                 return 2; /* Don't set color */
388         } else if (!has_mcol) {
389                 if (tface) glColor3f(1.0, 1.0, 1.0);
390                 else {
391                         if(ma) {
392                                 float col[3];
393                                 if(Gtexdraw.color_profile) linearrgb_to_srgb_v3_v3(col, &ma->r);
394                                 else copy_v3_v3(col, &ma->r);
395                                 
396                                 glColor3fv(col);
397                         }
398                         else glColor3f(1.0, 1.0, 1.0);
399                 }
400                 return 2; /* Don't set color */
401         } else {
402                 return 1; /* Set color from mcol */
403         }
404 }
405
406 static int draw_mcol__set_draw_legacy(MTFace *UNUSED(tface), int has_mcol, int UNUSED(matnr))
407 {
408         if (has_mcol) return 1;
409         else return 2;
410 }
411
412 static int draw_tface__set_draw(MTFace *tface, int has_mcol, int matnr)
413 {
414         Material *ma= give_current_material(Gtexdraw.ob, matnr+1);
415
416         if (ma && (ma->game.flag & GEMAT_INVISIBLE)) return 0;
417
418         if (tface && set_draw_settings_cached(0, tface, ma, Gtexdraw)) {
419                 return 2; /* Don't set color */
420         } else if (tface && tface->mode&TF_OBCOL) {
421                 return 2; /* Don't set color */
422         } else if (!has_mcol) {
423                 return 1; /* Don't set color */
424         } else {
425                 return 1; /* Set color from mcol */
426         }
427 }
428 static void add_tface_color_layer(DerivedMesh *dm)
429 {
430         MTFace *tface = DM_get_face_data_layer(dm, CD_MTFACE);
431         MFace *mface = DM_get_face_data_layer(dm, CD_MFACE);
432         MCol *finalCol;
433         int i,j;
434         MCol *mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL);
435         if(!mcol)
436                 mcol = dm->getFaceDataArray(dm, CD_MCOL);
437
438         finalCol = MEM_mallocN(sizeof(MCol)*4*dm->getNumFaces(dm),"add_tface_color_layer");
439         for(i=0;i<dm->getNumFaces(dm);i++) {
440                 Material *ma= give_current_material(Gtexdraw.ob, mface[i].mat_nr+1);
441
442                 if (ma && (ma->game.flag&GEMAT_INVISIBLE)) {
443                         if( mcol )
444                                 memcpy(&finalCol[i*4],&mcol[i*4],sizeof(MCol)*4);
445                         else
446                                 for(j=0;j<4;j++) {
447                                         finalCol[i*4+j].b = 255;
448                                         finalCol[i*4+j].g = 255;
449                                         finalCol[i*4+j].r = 255;
450                                 }
451                 }
452                 else if (tface && mface && set_draw_settings_cached(0, tface, ma, Gtexdraw)) {
453                         for(j=0;j<4;j++) {
454                                 finalCol[i*4+j].b = 255;
455                                 finalCol[i*4+j].g = 0;
456                                 finalCol[i*4+j].r = 255;
457                         }
458                 } else if (tface && tface->mode&TF_OBCOL) {
459                         for(j=0;j<4;j++) {
460                                 finalCol[i*4+j].b = FTOCHAR(Gtexdraw.obcol[0]);
461                                 finalCol[i*4+j].g = FTOCHAR(Gtexdraw.obcol[1]);
462                                 finalCol[i*4+j].r = FTOCHAR(Gtexdraw.obcol[2]);
463                         }
464                 } else if (!mcol) {
465                         if (tface) {
466                                 for(j=0;j<4;j++) {
467                                         finalCol[i*4+j].b = 255;
468                                         finalCol[i*4+j].g = 255;
469                                         finalCol[i*4+j].r = 255;
470                                 }
471                         }
472                         else {
473                                 float col[3];
474                                 Material *ma= give_current_material(Gtexdraw.ob, mface[i].mat_nr+1);
475                                 
476                                 if(ma) {
477                                         if(Gtexdraw.color_profile) linearrgb_to_srgb_v3_v3(col, &ma->r);
478                                         else copy_v3_v3(col, &ma->r);
479                                         
480                                         for(j=0;j<4;j++) {
481                                                 finalCol[i*4+j].b = FTOCHAR(col[0]);
482                                                 finalCol[i*4+j].g = FTOCHAR(col[1]);
483                                                 finalCol[i*4+j].r = FTOCHAR(col[2]);
484                                         }
485                                 }
486                                 else
487                                         for(j=0;j<4;j++) {
488                                                 finalCol[i*4+j].b = 255;
489                                                 finalCol[i*4+j].g = 255;
490                                                 finalCol[i*4+j].r = 255;
491                                         }
492                         }
493                 } else {
494                         for(j=0;j<4;j++) {
495                                 finalCol[i*4+j].r = mcol[i*4+j].r;
496                                 finalCol[i*4+j].g = mcol[i*4+j].g;
497                                 finalCol[i*4+j].b = mcol[i*4+j].b;
498                         }
499                 }
500         }
501         CustomData_add_layer( &dm->faceData, CD_TEXTURE_MCOL, CD_ASSIGN, finalCol, dm->numFaceData );
502 }
503
504 static int draw_tface_mapped__set_draw(void *userData, int index)
505 {
506         Mesh *me = (Mesh*)userData;
507         MTFace *tface = (me->mtface)? &me->mtface[index]: NULL;
508         MFace *mface = &me->mface[index];
509         const int matnr = mface->mat_nr;
510         if (mface->flag & ME_HIDE) return 0;
511         return draw_tface__set_draw(tface, (me->mcol != NULL), matnr);
512 }
513
514 static int draw_em_tf_mapped__set_draw(void *userData, int index)
515 {
516         struct {DerivedMesh *dm; EditMesh *em; short has_mcol; short has_mtface;} *data = userData;
517         EditMesh *em = data->em;
518         EditFace *efa= EM_get_face_for_index(index);
519         MTFace *tface;
520         int matnr;
521
522         if (efa->h)
523                 return 0;
524
525         tface = data->has_mtface ? CustomData_em_get(&em->fdata, efa->data, CD_MTFACE) : NULL;
526         matnr = efa->mat_nr;
527
528         return draw_tface__set_draw_legacy(tface, data->has_mcol, matnr);
529 }
530
531 static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r)
532 {
533         Mesh *me = (Mesh*)userData;
534
535         if (me->mat && me->mface) {
536                 Material *ma= me->mat[me->mface[index].mat_nr];
537                 if (ma && (ma->game.flag & GEMAT_INVISIBLE)) {
538                         return 0;
539                 }
540         }
541
542         *drawSmooth_r = 1;
543         return 1;
544 }
545
546 static void draw_mesh_text(Scene *scene, Object *ob, int glsl)
547 {
548         Mesh *me = ob->data;
549         DerivedMesh *ddm;
550         MFace *mf, *mface= me->mface;
551         MTFace *tface= me->mtface;
552         MCol *mcol= me->mcol;   /* why does mcol exist? */
553         bProperty *prop = get_ob_property(ob, "Text");
554         GPUVertexAttribs gattribs;
555         int a, totface= me->totface;
556
557         /* don't draw without tfaces */
558         if(!tface)
559                 return;
560
561         /* don't draw when editing */
562         if(ob->mode & OB_MODE_EDIT)
563                 return;
564         else if(ob==OBACT)
565                 if(paint_facesel_test(ob) || paint_vertsel_test(ob))
566                         return;
567
568         ddm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
569
570         for(a=0, mf=mface; a<totface; a++, tface++, mf++) {
571                 short matnr= mf->mat_nr;
572                 int mf_smooth= mf->flag & ME_SMOOTH;
573                 Material *mat = me->mat[matnr];
574                 int mode= mat->game.flag;
575
576                 if (!(mode&GEMAT_INVISIBLE) && (mode&GEMAT_TEXT)) {
577                         float v1[3], v2[3], v3[3], v4[3];
578                         char string[MAX_PROPSTRING];
579                         int characters, i, glattrib= -1, badtex= 0;
580
581                         if(glsl) {
582                                 GPU_enable_material(matnr+1, &gattribs);
583
584                                 for(i=0; i<gattribs.totlayer; i++) {
585                                         if(gattribs.layer[i].type == CD_MTFACE) {
586                                                 glattrib = gattribs.layer[i].glindex;
587                                                 break;
588                                         }
589                                 }
590                         }
591                         else {
592                                 badtex = set_draw_settings_cached(0, tface, mat, Gtexdraw);
593                                 if (badtex) {
594                                         if (mcol) mcol+=4;
595                                         continue;
596                                 }
597                         }
598
599                         ddm->getVertCo(ddm, mf->v1, v1);
600                         ddm->getVertCo(ddm, mf->v2, v2);
601                         ddm->getVertCo(ddm, mf->v3, v3);
602                         if (mf->v4) ddm->getVertCo(ddm, mf->v4, v4);
603
604                         // The BM_FONT handling is in the gpu module, shared with the
605                         // game engine, was duplicated previously
606
607                         set_property_valstr(prop, string);
608                         characters = strlen(string);
609                         
610                         if(!BKE_image_get_ibuf(tface->tpage, NULL))
611                                 characters = 0;
612
613                         if (!mf_smooth) {
614                                 float nor[3];
615
616                                 normal_tri_v3( nor,v1, v2, v3);
617
618                                 glNormal3fv(nor);
619                         }
620
621                         GPU_render_text(tface, mode, string, characters,
622                                 (unsigned int*)mcol, v1, v2, v3, (mf->v4? v4: NULL), glattrib);
623                 }
624                 if (mcol) {
625                         mcol+=4;
626                 }
627         }
628
629         ddm->release(ddm);
630 }
631
632 static int compareDrawOptions(void *userData, int cur_index, int next_index)
633 {
634         DerivedMesh *dm= (DerivedMesh*) userData;
635         MFace *mf = DM_get_face_data_layer(dm, CD_MFACE);
636         MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
637
638         if(mf && mf[cur_index].mat_nr != mf[next_index].mat_nr)
639                 return 0;
640
641         if(tf && tf[cur_index].tpage != tf[next_index].tpage)
642                 return 0;
643
644         return 1;
645 }
646
647 static int compareDrawOptionsEm(void *userData, int cur_index, int next_index)
648 {
649         struct {DerivedMesh *dm; EditMesh *em; short has_mcol; short has_mtface;} *data= userData;
650         MFace *mf = DM_get_face_data_layer(data->dm, CD_MFACE);
651         MTFace *tf = DM_get_face_data_layer(data->dm, CD_MTFACE);
652
653         if(mf && mf[cur_index].mat_nr != mf[next_index].mat_nr)
654                 return 0;
655
656         if(tf && tf[cur_index].tpage != tf[next_index].tpage)
657                 return 0;
658
659         return 1;
660 }
661
662 void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, DerivedMesh *dm, int draw_flags)
663 {
664         Mesh *me= ob->data;
665         
666         /* correct for negative scale */
667         if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
668         else glFrontFace(GL_CCW);
669         
670         /* draw the textured mesh */
671         draw_textured_begin(scene, v3d, rv3d, ob);
672
673         glColor4f(1.0f,1.0f,1.0f,1.0f);
674
675         if(ob->mode & OB_MODE_EDIT) {
676                 struct {DerivedMesh *dm; EditMesh *em; short has_mcol; short has_mtface;} data;
677
678                 data.dm = dm;
679                 data.em= me->edit_mesh;
680                 data.has_mcol= CustomData_has_layer(&me->edit_mesh->fdata, CD_MCOL);
681                 data.has_mtface= CustomData_has_layer(&me->edit_mesh->fdata, CD_MTFACE);
682
683                 dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, compareDrawOptionsEm, &data);
684         }
685         else if(draw_flags & DRAW_FACE_SELECT) {
686                 if(ob->mode & OB_MODE_WEIGHT_PAINT)
687                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, GPU_enable_material, NULL, me, 1);
688                 else
689                         dm->drawMappedFacesTex(dm, me->mface ? draw_tface_mapped__set_draw : NULL, NULL, me);
690         }
691         else {
692                 if(GPU_buffer_legacy(dm)) {
693                         if (draw_flags & DRAW_DYNAMIC_PAINT_PREVIEW)
694                                 dm->drawFacesTex(dm, draw_mcol__set_draw_legacy, NULL, NULL);
695                         else 
696                                 dm->drawFacesTex(dm, draw_tface__set_draw_legacy, NULL, NULL);
697                 }
698                 else {
699                         if(!CustomData_has_layer(&dm->faceData,CD_TEXTURE_MCOL))
700                                 add_tface_color_layer(dm);
701
702                         dm->drawFacesTex(dm, draw_tface__set_draw, compareDrawOptions, dm);
703                 }
704         }
705
706         /* draw game engine text hack */
707         if(get_ob_property(ob, "Text")) 
708                 draw_mesh_text(scene, ob, 0);
709
710         draw_textured_end();
711         
712         /* draw edges and selected faces over textured mesh */
713         if(!(ob == scene->obedit) && (draw_flags & DRAW_FACE_SELECT))
714                 draw_mesh_face_select(rv3d, me, dm);
715
716         /* reset from negative scale correction */
717         glFrontFace(GL_CCW);
718         
719         /* in editmode, the blend mode needs to be set incase it was ADD */
720         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
721 }
722
723 /************************** NEW SHADING NODES ********************************/
724
725 typedef struct TexMatCallback {
726         Scene *scene;
727         Object *ob;
728         Mesh *me;
729         DerivedMesh *dm;
730 } TexMatCallback;
731
732 static void tex_mat_set_material_cb(void *UNUSED(userData), int mat_nr, void *attribs)
733 {
734         /* all we have to do here is simply enable the GLSL material, but note
735            that the GLSL code will give different result depending on the drawtype,
736            in texture draw mode it will output the active texture node, in material
737            draw mode it will show the full material. */
738         GPU_enable_material(mat_nr, attribs);
739 }
740
741 static void tex_mat_set_texture_cb(void *userData, int mat_nr, void *attribs)
742 {
743         /* texture draw mode without GLSL */
744         TexMatCallback *data= (TexMatCallback*)userData;
745         GPUVertexAttribs *gattribs = attribs;
746         Image *ima;
747         ImageUser *iuser;
748         bNode *node;
749         int texture_set= 0;
750
751         /* draw image texture if we find one */
752         if(ED_object_get_active_image(data->ob, mat_nr, &ima, &iuser, &node)) {
753                 /* get openl texture */
754                 int mipmap= 1;
755                 int bindcode= (ima)? GPU_verify_image(ima, iuser, 0, 0, mipmap): 0;
756                 float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
757
758                 if(bindcode) {
759                         NodeTexBase *texbase= node->storage;
760
761                         /* disable existing material */
762                         GPU_disable_material();
763                         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, zero);
764                         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, zero);
765                         glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 0);
766
767                         /* bind texture */
768                         glEnable(GL_COLOR_MATERIAL);
769                         glEnable(GL_TEXTURE_2D);
770
771                         glBindTexture(GL_TEXTURE_2D, ima->bindcode);
772                         glColor3f(1.0f, 1.0f, 1.0f);
773
774                         glMatrixMode(GL_TEXTURE);
775                         glLoadMatrixf(texbase->tex_mapping.mat);
776                         glMatrixMode(GL_MODELVIEW);
777
778                         /* use active UV texture layer */
779                         memset(gattribs, 0, sizeof(*gattribs));
780
781                         gattribs->layer[0].type= CD_MTFACE;
782                         gattribs->layer[0].name[0]= '\0';
783                         gattribs->layer[0].gltexco= 1;
784                         gattribs->totlayer= 1;
785
786                         texture_set= 1;
787                 }
788         }
789
790         if(!texture_set) {
791                 glMatrixMode(GL_TEXTURE);
792                 glLoadIdentity();
793                 glMatrixMode(GL_MODELVIEW);
794
795                 /* disable texture */
796                 glDisable(GL_TEXTURE_2D);
797                 glDisable(GL_COLOR_MATERIAL);
798
799                 /* draw single color */
800                 GPU_enable_material(mat_nr, attribs);
801         }
802 }
803
804 static int tex_mat_set_face_mesh_cb(void *userData, int index)
805 {
806         /* faceselect mode face hiding */
807         TexMatCallback *data= (TexMatCallback*)userData;
808         Mesh *me = (Mesh*)data->me;
809         MFace *mface = &me->mface[index];
810
811         return !(mface->flag & ME_HIDE);
812 }
813
814 static int tex_mat_set_face_editmesh_cb(void *UNUSED(userData), int index)
815 {
816         /* editmode face hiding */
817         EditFace *efa= EM_get_face_for_index(index);
818
819         return !(efa->h);
820 }
821
822 void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, DerivedMesh *dm, int draw_flags)
823 {
824         if((!scene_use_new_shading_nodes(scene)) || (draw_flags & DRAW_DYNAMIC_PAINT_PREVIEW)) {
825                 draw_mesh_textured_old(scene, v3d, rv3d, ob, dm, draw_flags);
826                 return;
827         }
828
829         /* set opengl state for negative scale & color */
830         if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
831         else glFrontFace(GL_CCW);
832
833         glEnable(GL_LIGHTING);
834
835         if(ob->mode & OB_MODE_WEIGHT_PAINT) {
836                 /* weight paint mode exception */
837                 int useColors= 1;
838
839                 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions,
840                         GPU_enable_material, NULL, ob->data, useColors);
841         }
842         else {
843                 Mesh *me= ob->data;
844                 TexMatCallback data = {scene, ob, me, dm};
845                 int (*set_face_cb)(void*, int);
846                 int glsl;
847                 
848                 /* face hiding callback depending on mode */
849                 if(ob == scene->obedit)
850                         set_face_cb= tex_mat_set_face_editmesh_cb;
851                 else if(draw_flags & DRAW_FACE_SELECT)
852                         set_face_cb= tex_mat_set_face_mesh_cb;
853                 else
854                         set_face_cb= NULL;
855
856                 /* test if we can use glsl */
857                 glsl= (v3d->drawtype == OB_MATERIAL) && GPU_glsl_support();
858
859                 GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
860
861                 if(glsl) {
862                         /* draw glsl */
863                         dm->drawMappedFacesMat(dm,
864                                 tex_mat_set_material_cb,
865                                 set_face_cb, &data);
866                 }
867                 else {
868                         float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
869
870                         /* draw textured */
871                         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, zero);
872                         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, zero);
873                         glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 0);
874
875                         dm->drawMappedFacesMat(dm,
876                                 tex_mat_set_texture_cb,
877                                 set_face_cb, &data);
878                 }
879
880                 GPU_end_object_materials();
881         }
882
883         /* reset opengl state */
884         glDisable(GL_COLOR_MATERIAL);
885         glDisable(GL_TEXTURE_2D);
886         glDisable(GL_LIGHTING);
887         glBindTexture(GL_TEXTURE_2D, 0);
888         glFrontFace(GL_CCW);
889
890         glMatrixMode(GL_TEXTURE);
891         glLoadIdentity();
892         glMatrixMode(GL_MODELVIEW);
893
894         /* faceselect mode drawing over textured mesh */
895         if(!(ob == scene->obedit) && (draw_flags & DRAW_FACE_SELECT))
896                 draw_mesh_face_select(rv3d, ob->data, dm);
897 }
898