e52a9217673558fe2952d0c808a127ad026c2b6c
[blender.git] / source / blender / blenkernel / intern / material.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  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/blenkernel/intern/material.c
29  *  \ingroup bke
30  */
31
32
33 #include <string.h>
34 #include <math.h>
35 #include <stddef.h>
36
37 #include "MEM_guardedalloc.h"
38
39 #include "DNA_curve_types.h"
40 #include "DNA_material_types.h"
41 #include "DNA_mesh_types.h"
42 #include "DNA_meshdata_types.h"
43 #include "DNA_customdata_types.h"
44 #include "DNA_ID.h"
45 #include "DNA_meta_types.h"
46 #include "DNA_node_types.h"
47 #include "DNA_object_types.h"
48 #include "DNA_scene_types.h"
49
50 #include "BLI_math.h"           
51 #include "BLI_listbase.h"               
52 #include "BLI_utildefines.h"
53 #include "BLI_bpath.h"
54 #include "BLI_string.h"
55
56 #include "BKE_animsys.h"
57 #include "BKE_displist.h"
58 #include "BKE_global.h"
59 #include "BKE_icons.h"
60 #include "BKE_image.h"
61 #include "BKE_library.h"
62 #include "BKE_main.h"
63 #include "BKE_material.h"
64 #include "BKE_mesh.h"
65 #include "BKE_node.h"
66 #include "BKE_curve.h"
67
68 #include "GPU_material.h"
69
70 /* used in UI and render */
71 Material defmaterial;
72
73 /* called on startup, creator.c */
74 void init_def_material(void)
75 {
76         init_material(&defmaterial);
77 }
78
79 /* not material itself */
80 void free_material(Material *ma)
81 {
82         MTex *mtex;
83         int a;
84         
85         for (a=0; a<MAX_MTEX; a++) {
86                 mtex= ma->mtex[a];
87                 if (mtex && mtex->tex) mtex->tex->id.us--;
88                 if (mtex) MEM_freeN(mtex);
89         }
90         
91         if (ma->ramp_col) MEM_freeN(ma->ramp_col);
92         if (ma->ramp_spec) MEM_freeN(ma->ramp_spec);
93         
94         BKE_free_animdata((ID *)ma);
95         
96         if (ma->preview)
97                 BKE_previewimg_free(&ma->preview);
98         BKE_icon_delete((struct ID*)ma);
99         ma->id.icon_id = 0;
100         
101         /* is no lib link block, but material extension */
102         if (ma->nodetree) {
103                 ntreeFreeTree(ma->nodetree);
104                 MEM_freeN(ma->nodetree);
105         }
106
107         if (ma->gpumaterial.first)
108                 GPU_material_free(ma);
109 }
110
111 void init_material(Material *ma)
112 {
113         ma->r= ma->g= ma->b= ma->ref= 0.8;
114         ma->specr= ma->specg= ma->specb= 1.0;
115         ma->mirr= ma->mirg= ma->mirb= 1.0;
116         ma->spectra= 1.0;
117         ma->amb= 1.0;
118         ma->alpha= 1.0;
119         ma->spec= ma->hasize= 0.5;
120         ma->har= 50;
121         ma->starc= ma->ringc= 4;
122         ma->linec= 12;
123         ma->flarec= 1;
124         ma->flaresize= ma->subsize= 1.0;
125         ma->flareboost= 1;
126         ma->seed2= 6;
127         ma->friction= 0.5;
128         ma->refrac= 4.0;
129         ma->roughness= 0.5;
130         ma->param[0]= 0.5;
131         ma->param[1]= 0.1;
132         ma->param[2]= 0.5;
133         ma->param[3]= 0.1;
134         ma->rms= 0.1;
135         ma->darkness= 1.0;      
136         
137         ma->strand_sta= ma->strand_end= 1.0f;
138         
139         ma->ang= 1.0;
140         ma->ray_depth= 2;
141         ma->ray_depth_tra= 2;
142         ma->fresnel_mir= 0.0;
143         ma->fresnel_tra= 0.0;
144         ma->fresnel_tra_i= 1.25;
145         ma->fresnel_mir_i= 1.25;
146         ma->tx_limit= 0.0;
147         ma->tx_falloff= 1.0;
148         ma->shad_alpha= 1.0f;
149         
150         ma->gloss_mir = ma->gloss_tra= 1.0;
151         ma->samp_gloss_mir = ma->samp_gloss_tra= 18;
152         ma->adapt_thresh_mir = ma->adapt_thresh_tra = 0.005;
153         ma->dist_mir = 0.0;
154         ma->fadeto_mir = MA_RAYMIR_FADETOSKY;
155         
156         ma->rampfac_col= 1.0;
157         ma->rampfac_spec= 1.0;
158         ma->pr_lamp= 3;                 /* two lamps, is bits */
159         ma->pr_type= MA_SPHERE;
160
161         ma->sss_radius[0]= 1.0f;
162         ma->sss_radius[1]= 1.0f;
163         ma->sss_radius[2]= 1.0f;
164         ma->sss_col[0]= 1.0f;
165         ma->sss_col[1]= 1.0f;
166         ma->sss_col[2]= 1.0f;
167         ma->sss_error= 0.05f;
168         ma->sss_scale= 0.1f;
169         ma->sss_ior= 1.3f;
170         ma->sss_colfac= 1.0f;
171         ma->sss_texfac= 0.0f;
172         ma->sss_front= 1.0f;
173         ma->sss_back= 1.0f;
174
175         ma->vol.density = 1.0f;
176         ma->vol.emission = 0.0f;
177         ma->vol.scattering = 1.0f;
178         ma->vol.reflection = 1.0f;
179         ma->vol.transmission_col[0] = ma->vol.transmission_col[1] = ma->vol.transmission_col[2] = 1.0f;
180         ma->vol.reflection_col[0] = ma->vol.reflection_col[1] = ma->vol.reflection_col[2] = 1.0f;
181         ma->vol.emission_col[0] = ma->vol.emission_col[1] = ma->vol.emission_col[2] = 1.0f;
182         ma->vol.density_scale = 1.0f;
183         ma->vol.depth_cutoff = 0.01f;
184         ma->vol.stepsize_type = MA_VOL_STEP_RANDOMIZED;
185         ma->vol.stepsize = 0.2f;
186         ma->vol.shade_type = MA_VOL_SHADE_SHADED;
187         ma->vol.shadeflag |= MA_VOL_PRECACHESHADING;
188         ma->vol.precache_resolution = 50;
189         ma->vol.ms_spread = 0.2f;
190         ma->vol.ms_diff = 1.f;
191         ma->vol.ms_intensity = 1.f;
192         
193         ma->game.flag = GEMAT_BACKCULL;
194         ma->game.alpha_blend=0;
195         ma->game.face_orientation=0;
196         
197         ma->mode= MA_TRACEBLE|MA_SHADBUF|MA_SHADOW|MA_RAYBIAS|MA_TANGENT_STR|MA_ZTRANSP;
198         ma->shade_flag= MA_APPROX_OCCLUSION;
199         ma->preview = NULL;
200 }
201
202 Material *add_material(const char *name)
203 {
204         Material *ma;
205
206         ma= alloc_libblock(&G.main->mat, ID_MA, name);
207         
208         init_material(ma);
209         
210         return ma;      
211 }
212
213 /* XXX keep synced with next function */
214 Material *copy_material(Material *ma)
215 {
216         Material *man;
217         int a;
218         
219         man= copy_libblock(&ma->id);
220         
221         id_lib_extern((ID *)man->group);
222         
223         for (a=0; a<MAX_MTEX; a++) {
224                 if (ma->mtex[a]) {
225                         man->mtex[a]= MEM_mallocN(sizeof(MTex), "copymaterial");
226                         memcpy(man->mtex[a], ma->mtex[a], sizeof(MTex));
227                         id_us_plus((ID *)man->mtex[a]->tex);
228                 }
229         }
230         
231         if (ma->ramp_col) man->ramp_col= MEM_dupallocN(ma->ramp_col);
232         if (ma->ramp_spec) man->ramp_spec= MEM_dupallocN(ma->ramp_spec);
233         
234         if (ma->preview) man->preview = BKE_previewimg_copy(ma->preview);
235
236         if (ma->nodetree) {
237                 man->nodetree= ntreeCopyTree(ma->nodetree);     /* 0 == full new tree */
238         }
239
240         man->gpumaterial.first= man->gpumaterial.last= NULL;
241         
242         return man;
243 }
244
245 /* XXX (see above) material copy without adding to main dbase */
246 Material *localize_material(Material *ma)
247 {
248         Material *man;
249         int a;
250         
251         man= copy_libblock(&ma->id);
252         BLI_remlink(&G.main->mat, man);
253
254         /* no increment for texture ID users, in previewrender.c it prevents decrement */
255         for (a=0; a<MAX_MTEX; a++) {
256                 if (ma->mtex[a]) {
257                         man->mtex[a]= MEM_mallocN(sizeof(MTex), "copymaterial");
258                         memcpy(man->mtex[a], ma->mtex[a], sizeof(MTex));
259                 }
260         }
261         
262         if (ma->ramp_col) man->ramp_col= MEM_dupallocN(ma->ramp_col);
263         if (ma->ramp_spec) man->ramp_spec= MEM_dupallocN(ma->ramp_spec);
264         
265         man->preview = NULL;
266         
267         if (ma->nodetree)
268                 man->nodetree= ntreeLocalize(ma->nodetree);
269         
270         man->gpumaterial.first= man->gpumaterial.last= NULL;
271         
272         return man;
273 }
274
275 static void extern_local_material(Material *ma)
276 {
277         int i;
278         for (i=0; i < MAX_MTEX; i++) {
279                 if (ma->mtex[i]) id_lib_extern((ID *)ma->mtex[i]->tex);
280         }
281 }
282
283 void make_local_material(Material *ma)
284 {
285         Main *bmain= G.main;
286         Object *ob;
287         Mesh *me;
288         Curve *cu;
289         MetaBall *mb;
290         int a, is_local= FALSE, is_lib= FALSE;
291
292         /* - only lib users: do nothing
293          * - only local users: set flag
294          * - mixed: make copy
295          */
296         
297         if (ma->id.lib==NULL) return;
298
299         /* One local user; set flag and return. */
300         if (ma->id.us==1) {
301                 id_clear_lib_data(bmain, &ma->id);
302                 extern_local_material(ma);
303                 return;
304         }
305
306         /* Check which other IDs reference this one to determine if it's used by
307          * lib or local */
308         /* test objects */
309         ob= bmain->object.first;
310         while (ob) {
311                 if (ob->mat) {
312                         for (a=0; a<ob->totcol; a++) {
313                                 if (ob->mat[a]==ma) {
314                                         if (ob->id.lib) is_lib= TRUE;
315                                         else is_local= TRUE;
316                                 }
317                         }
318                 }
319                 ob= ob->id.next;
320         }
321         /* test meshes */
322         me= bmain->mesh.first;
323         while (me) {
324                 if (me->mat) {
325                         for (a=0; a<me->totcol; a++) {
326                                 if (me->mat[a]==ma) {
327                                         if (me->id.lib) is_lib= TRUE;
328                                         else is_local= TRUE;
329                                 }
330                         }
331                 }
332                 me= me->id.next;
333         }
334         /* test curves */
335         cu= bmain->curve.first;
336         while (cu) {
337                 if (cu->mat) {
338                         for (a=0; a<cu->totcol; a++) {
339                                 if (cu->mat[a]==ma) {
340                                         if (cu->id.lib) is_lib= TRUE;
341                                         else is_local= TRUE;
342                                 }
343                         }
344                 }
345                 cu= cu->id.next;
346         }
347         /* test mballs */
348         mb= bmain->mball.first;
349         while (mb) {
350                 if (mb->mat) {
351                         for (a=0; a<mb->totcol; a++) {
352                                 if (mb->mat[a]==ma) {
353                                         if (mb->id.lib) is_lib= TRUE;
354                                         else is_local= TRUE;
355                                 }
356                         }
357                 }
358                 mb= mb->id.next;
359         }
360
361         /* Only local users. */
362         if (is_local && is_lib == FALSE) {
363                 id_clear_lib_data(bmain, &ma->id);
364                 extern_local_material(ma);
365         }
366         /* Both user and local, so copy. */
367         else if (is_local && is_lib) {
368                 Material *ma_new= copy_material(ma);
369
370                 ma_new->id.us= 0;
371
372                 /* Remap paths of new ID using old library as base. */
373                 BKE_id_lib_local_paths(bmain, ma->id.lib, &ma_new->id);
374
375                 /* do objects */
376                 ob= bmain->object.first;
377                 while (ob) {
378                         if (ob->mat) {
379                                 for (a=0; a<ob->totcol; a++) {
380                                         if (ob->mat[a]==ma) {
381                                                 if (ob->id.lib==NULL) {
382                                                         ob->mat[a]= ma_new;
383                                                         ma_new->id.us++;
384                                                         ma->id.us--;
385                                                 }
386                                         }
387                                 }
388                         }
389                         ob= ob->id.next;
390                 }
391                 /* do meshes */
392                 me= bmain->mesh.first;
393                 while (me) {
394                         if (me->mat) {
395                                 for (a=0; a<me->totcol; a++) {
396                                         if (me->mat[a]==ma) {
397                                                 if (me->id.lib==NULL) {
398                                                         me->mat[a]= ma_new;
399                                                         ma_new->id.us++;
400                                                         ma->id.us--;
401                                                 }
402                                         }
403                                 }
404                         }
405                         me= me->id.next;
406                 }
407                 /* do curves */
408                 cu= bmain->curve.first;
409                 while (cu) {
410                         if (cu->mat) {
411                                 for (a=0; a<cu->totcol; a++) {
412                                         if (cu->mat[a]==ma) {
413                                                 if (cu->id.lib==NULL) {
414                                                         cu->mat[a]= ma_new;
415                                                         ma_new->id.us++;
416                                                         ma->id.us--;
417                                                 }
418                                         }
419                                 }
420                         }
421                         cu= cu->id.next;
422                 }
423                 /* do mballs */
424                 mb= bmain->mball.first;
425                 while (mb) {
426                         if (mb->mat) {
427                                 for (a=0; a<mb->totcol; a++) {
428                                         if (mb->mat[a]==ma) {
429                                                 if (mb->id.lib==NULL) {
430                                                         mb->mat[a]= ma_new;
431                                                         ma_new->id.us++;
432                                                         ma->id.us--;
433                                                 }
434                                         }
435                                 }
436                         }
437                         mb= mb->id.next;
438                 }
439         }
440 }
441
442 /* for curve, mball, mesh types */
443 void extern_local_matarar(struct Material **matar, short totcol)
444 {
445         short i;
446         for (i= 0; i < totcol; i++) {
447                 id_lib_extern((ID *)matar[i]);
448         }
449 }
450
451 Material ***give_matarar(Object *ob)
452 {
453         Mesh *me;
454         Curve *cu;
455         MetaBall *mb;
456         
457         if (ob->type==OB_MESH) {
458                 me= ob->data;
459                 return &(me->mat);
460         }
461         else if (ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
462                 cu= ob->data;
463                 return &(cu->mat);
464         }
465         else if (ob->type==OB_MBALL) {
466                 mb= ob->data;
467                 return &(mb->mat);
468         }
469         return NULL;
470 }
471
472 short *give_totcolp(Object *ob)
473 {
474         Mesh *me;
475         Curve *cu;
476         MetaBall *mb;
477         
478         if (ob->type==OB_MESH) {
479                 me= ob->data;
480                 return &(me->totcol);
481         }
482         else if (ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
483                 cu= ob->data;
484                 return &(cu->totcol);
485         }
486         else if (ob->type==OB_MBALL) {
487                 mb= ob->data;
488                 return &(mb->totcol);
489         }
490         return NULL;
491 }
492
493 /* same as above but for ID's */
494 Material ***give_matarar_id(ID *id)
495 {
496         switch (GS(id->name)) {
497         case ID_ME:
498                 return &(((Mesh *)id)->mat);
499                 break;
500         case ID_CU:
501                 return &(((Curve *)id)->mat);
502                 break;
503         case ID_MB:
504                 return &(((MetaBall *)id)->mat);
505                 break;
506         }
507         return NULL;
508 }
509
510 short *give_totcolp_id(ID *id)
511 {
512         switch (GS(id->name)) {
513         case ID_ME:
514                 return &(((Mesh *)id)->totcol);
515                 break;
516         case ID_CU:
517                 return &(((Curve *)id)->totcol);
518                 break;
519         case ID_MB:
520                 return &(((MetaBall *)id)->totcol);
521                 break;
522         }
523         return NULL;
524 }
525
526 static void data_delete_material_index_id(ID *id, short index)
527 {
528         switch (GS(id->name)) {
529         case ID_ME:
530                 mesh_delete_material_index((Mesh *)id, index);
531                 break;
532         case ID_CU:
533                 BKE_curve_delete_material_index((Curve *)id, index);
534                 break;
535         case ID_MB:
536                 /* meta-elems don't have materials atm */
537                 break;
538         }
539 }
540
541 void material_append_id(ID *id, Material *ma)
542 {
543         Material ***matar;
544         if ((matar= give_matarar_id(id))) {
545                 short *totcol= give_totcolp_id(id);
546                 Material **mat= MEM_callocN(sizeof(void *) * ((*totcol) + 1), "newmatar");
547                 if (*totcol) memcpy(mat, *matar, sizeof(void *) * (*totcol));
548                 if (*matar) MEM_freeN(*matar);
549
550                 *matar= mat;
551                 (*matar)[(*totcol)++]= ma;
552
553                 id_us_plus((ID *)ma);
554                 test_object_materials(id);
555         }
556 }
557
558 Material *material_pop_id(ID *id, int index_i, int remove_material_slot)
559 {
560         short index= (short)index_i;
561         Material *ret= NULL;
562         Material ***matar;
563         if ((matar= give_matarar_id(id))) {
564                 short *totcol= give_totcolp_id(id);
565                 if (index >= 0 && index < (*totcol)) {
566                         ret= (*matar)[index];
567                         id_us_min((ID *)ret);
568
569                         if (remove_material_slot) {
570                                 if (*totcol <= 1) {
571                                         *totcol= 0;
572                                         MEM_freeN(*matar);
573                                         *matar= NULL;
574                                 }
575                                 else {
576                                         Material **mat;
577                                         if (index + 1 != (*totcol))
578                                                 memmove((*matar)+index, (*matar)+(index+1), sizeof(void *) * ((*totcol) - (index + 1)));
579
580                                         (*totcol)--;
581                                         
582                                         mat= MEM_callocN(sizeof(void *) * (*totcol), "newmatar");
583                                         memcpy(mat, *matar, sizeof(void *) * (*totcol));
584                                         MEM_freeN(*matar);
585
586                                         *matar= mat;
587                                         test_object_materials(id);
588                                 }
589
590                                 /* decrease mat_nr index */
591                                 data_delete_material_index_id(id, index);
592                         }
593
594                         /* don't remove material slot, only clear it*/
595                         else
596                                 (*matar)[index]= NULL;
597                 }
598         }
599         
600         return ret;
601 }
602
603 Material *give_current_material(Object *ob, short act)
604 {
605         Material ***matarar, *ma;
606         short *totcolp;
607         
608         if (ob==NULL) return NULL;
609         
610         /* if object cannot have material, totcolp==NULL */
611         totcolp= give_totcolp(ob);
612         if (totcolp==NULL || ob->totcol==0) return NULL;
613         
614         if (act<0) {
615                 printf("no!\n");
616         }
617         
618         if (act>ob->totcol) act= ob->totcol;
619         else if (act<=0) act= 1;
620
621         if (ob->matbits && ob->matbits[act-1]) {        /* in object */
622                 ma= ob->mat[act-1];
623         }
624         else {                                                          /* in data */
625
626                 /* check for inconsistency */
627                 if (*totcolp < ob->totcol)
628                         ob->totcol= *totcolp;
629                 if (act>ob->totcol) act= ob->totcol;
630
631                 matarar= give_matarar(ob);
632                 
633                 if (matarar && *matarar) ma= (*matarar)[act-1];
634                 else ma= NULL;
635                 
636         }
637         
638         return ma;
639 }
640
641 ID *material_from(Object *ob, short act)
642 {
643
644         if (ob==NULL) return NULL;
645
646         if (ob->totcol==0) return ob->data;
647         if (act==0) act= 1;
648
649         if (ob->matbits[act-1]) return (ID *)ob;
650         else return ob->data;
651 }
652
653 Material *give_node_material(Material *ma)
654 {
655         if (ma && ma->use_nodes && ma->nodetree) {
656                 bNode *node= nodeGetActiveID(ma->nodetree, ID_MA);
657
658                 if (node)
659                         return (Material *)node->id;
660         }
661
662         return NULL;
663 }
664
665 /* GS reads the memory pointed at in a specific ordering. There are,
666  * however two definitions for it. I have jotted them down here, both,
667  * but I think the first one is actually used. The thing is that
668  * big-endian systems might read this the wrong way round. OTOH, we
669  * constructed the IDs that are read out with this macro explicitly as
670  * well. I expect we'll sort it out soon... */
671
672 /* from blendef: */
673 #define GS(a)   (*((short *)(a)))
674
675 /* from misc_util: flip the bytes from x  */
676 /*  #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */
677
678 void resize_object_material(Object *ob, const short totcol)
679 {
680         Material **newmatar;
681         char *newmatbits;
682
683         if (totcol==0) {
684                 if (ob->totcol) {
685                         MEM_freeN(ob->mat);
686                         MEM_freeN(ob->matbits);
687                         ob->mat= NULL;
688                         ob->matbits= NULL;
689                 }
690         }
691         else if (ob->totcol<totcol) {
692                 newmatar= MEM_callocN(sizeof(void *)*totcol, "newmatar");
693                 newmatbits= MEM_callocN(sizeof(char)*totcol, "newmatbits");
694                 if (ob->totcol) {
695                         memcpy(newmatar, ob->mat, sizeof(void *)*ob->totcol);
696                         memcpy(newmatbits, ob->matbits, sizeof(char)*ob->totcol);
697                         MEM_freeN(ob->mat);
698                         MEM_freeN(ob->matbits);
699                 }
700                 ob->mat= newmatar;
701                 ob->matbits= newmatbits;
702         }
703         ob->totcol= totcol;
704         if (ob->totcol && ob->actcol==0) ob->actcol= 1;
705         if (ob->actcol>ob->totcol) ob->actcol= ob->totcol;
706 }
707
708 void test_object_materials(ID *id)
709 {
710         /* make the ob mat-array same size as 'ob->data' mat-array */
711         Object *ob;
712         short *totcol;
713
714         if (id==NULL || (totcol=give_totcolp_id(id))==NULL) {
715                 return;
716         }
717
718         for (ob= G.main->object.first; ob; ob= ob->id.next) {
719                 if (ob->data==id) {
720                         resize_object_material(ob, *totcol);
721                 }
722         }
723 }
724
725 void assign_material_id(ID *id, Material *ma, short act)
726 {
727         Material *mao, **matar, ***matarar;
728         short *totcolp;
729
730         if (act>MAXMAT) return;
731         if (act<1) act= 1;
732
733         /* prevent crashing when using accidentally */
734         BLI_assert(id->lib == NULL);
735         if (id->lib) return;
736
737         /* test arraylens */
738
739         totcolp= give_totcolp_id(id);
740         matarar= give_matarar_id(id);
741
742         if (totcolp==NULL || matarar==NULL) return;
743
744         if (act > *totcolp) {
745                 matar= MEM_callocN(sizeof(void *)*act, "matarray1");
746
747                 if (*totcolp) {
748                         memcpy(matar, *matarar, sizeof(void *)*(*totcolp));
749                         MEM_freeN(*matarar);
750                 }
751
752                 *matarar= matar;
753                 *totcolp= act;
754         }
755
756         /* in data */
757         mao= (*matarar)[act-1];
758         if (mao) mao->id.us--;
759         (*matarar)[act-1]= ma;
760
761         if (ma)
762                 id_us_plus((ID *)ma);
763
764         test_object_materials(id);
765 }
766
767 void assign_material(Object *ob, Material *ma, short act)
768 {
769         Material *mao, **matar, ***matarar;
770         char *matbits;
771         short *totcolp;
772
773         if (act>MAXMAT) return;
774         if (act<1) act= 1;
775         
776         /* prevent crashing when using accidentally */
777         BLI_assert(ob->id.lib == NULL);
778         if (ob->id.lib) return;
779         
780         /* test arraylens */
781         
782         totcolp= give_totcolp(ob);
783         matarar= give_matarar(ob);
784         
785         if (totcolp==NULL || matarar==NULL) return;
786         
787         if (act > *totcolp) {
788                 matar= MEM_callocN(sizeof(void *)*act, "matarray1");
789
790                 if (*totcolp) {
791                         memcpy(matar, *matarar, sizeof(void *)*(*totcolp));
792                         MEM_freeN(*matarar);
793                 }
794
795                 *matarar= matar;
796                 *totcolp= act;
797         }
798         
799         if (act > ob->totcol) {
800                 matar= MEM_callocN(sizeof(void *)*act, "matarray2");
801                 matbits= MEM_callocN(sizeof(char)*act, "matbits1");
802                 if ( ob->totcol) {
803                         memcpy(matar, ob->mat, sizeof(void *) * ob->totcol);
804                         memcpy(matbits, ob->matbits, sizeof(char)*(*totcolp));
805                         MEM_freeN(ob->mat);
806                         MEM_freeN(ob->matbits);
807                 }
808                 ob->mat= matar;
809                 ob->matbits= matbits;
810                 ob->totcol= act;
811
812                 /* copy object/mesh linking, or assign based on userpref */
813                 if (ob->actcol)
814                         ob->matbits[act-1]= ob->matbits[ob->actcol-1];
815                 else
816                         ob->matbits[act-1]= (U.flag & USER_MAT_ON_OB)? 1: 0;
817         }
818         
819         /* do it */
820
821         if (ob->matbits[act-1]) {       /* in object */
822                 mao= ob->mat[act-1];
823                 if (mao) mao->id.us--;
824                 ob->mat[act-1]= ma;
825         }
826         else {  /* in data */
827                 mao= (*matarar)[act-1];
828                 if (mao) mao->id.us--;
829                 (*matarar)[act-1]= ma;
830         }
831
832         if (ma)
833                 id_us_plus((ID *)ma);
834         test_object_materials(ob->data);
835 }
836
837 /* XXX - this calls many more update calls per object then are needed, could be optimized */
838 void assign_matarar(struct Object *ob, struct Material ***matar, short totcol)
839 {
840         int actcol_orig= ob->actcol;
841         short i;
842
843         while (object_remove_material_slot(ob)) {};
844
845         /* now we have the right number of slots */
846         for (i=0; i<totcol; i++)
847                 assign_material(ob, (*matar)[i], i+1);
848
849         if (actcol_orig > ob->totcol)
850                 actcol_orig= ob->totcol;
851
852         ob->actcol= actcol_orig;
853 }
854
855
856 short find_material_index(Object *ob, Material *ma)
857 {
858         Material ***matarar;
859         short a, *totcolp;
860         
861         if (ma==NULL) return 0;
862         
863         totcolp= give_totcolp(ob);
864         matarar= give_matarar(ob);
865         
866         if (totcolp==NULL || matarar==NULL) return 0;
867         
868         for (a=0; a<*totcolp; a++)
869                 if ((*matarar)[a]==ma)
870                    break;
871         if (a<*totcolp)
872                 return a+1;
873         return 0;          
874 }
875
876 int object_add_material_slot(Object *ob)
877 {
878         if (ob==NULL) return FALSE;
879         if (ob->totcol>=MAXMAT) return FALSE;
880         
881         assign_material(ob, NULL, ob->totcol+1);
882         ob->actcol= ob->totcol;
883         return TRUE;
884 }
885
886 static void do_init_render_material(Material *ma, int r_mode, float *amb)
887 {
888         MTex *mtex;
889         int a, needuv=0, needtang=0;
890         
891         if (ma->flarec==0) ma->flarec= 1;
892
893         /* add all texcoflags from mtex, texco and mapto were cleared in advance */
894         for (a=0; a<MAX_MTEX; a++) {
895                 
896                 /* separate tex switching */
897                 if (ma->septex & (1<<a)) continue;
898
899                 mtex= ma->mtex[a];
900                 if (mtex && mtex->tex && (mtex->tex->type | (mtex->tex->use_nodes && mtex->tex->nodetree) )) {
901                         
902                         ma->texco |= mtex->texco;
903                         ma->mapto |= mtex->mapto;
904
905                         /* always get derivatives for these textures */
906                         if (ELEM3(mtex->tex->type, TEX_IMAGE, TEX_PLUGIN, TEX_ENVMAP)) ma->texco |= TEXCO_OSA;
907                         else if (mtex->texflag & (MTEX_COMPAT_BUMP|MTEX_3TAP_BUMP|MTEX_5TAP_BUMP|MTEX_BICUBIC_BUMP)) ma->texco |= TEXCO_OSA;
908                         
909                         if (ma->texco & (TEXCO_ORCO|TEXCO_REFL|TEXCO_NORM|TEXCO_STRAND|TEXCO_STRESS)) needuv= 1;
910                         else if (ma->texco & (TEXCO_GLOB|TEXCO_UV|TEXCO_OBJECT|TEXCO_SPEED)) needuv= 1;
911                         else if (ma->texco & (TEXCO_LAVECTOR|TEXCO_VIEW|TEXCO_STICKY)) needuv= 1;
912
913                         if ((ma->mapto & MAP_NORM) && (mtex->normapspace == MTEX_NSPACE_TANGENT))
914                                 needtang= 1;
915                 }
916         }
917
918         if (needtang) ma->mode |= MA_NORMAP_TANG;
919         else ma->mode &= ~MA_NORMAP_TANG;
920         
921         if (ma->mode & (MA_VERTEXCOL|MA_VERTEXCOLP|MA_FACETEXTURE)) {
922                 needuv= 1;
923                 if (r_mode & R_OSA) ma->texco |= TEXCO_OSA;             /* for texfaces */
924         }
925         if (needuv) ma->texco |= NEED_UV;
926         
927         /* since the raytracer doesnt recalc O structs for each ray, we have to preset them all */
928         if (r_mode & R_RAYTRACE) {
929                 if ((ma->mode & (MA_RAYMIRROR|MA_SHADOW_TRA)) || ((ma->mode & MA_TRANSP) && (ma->mode & MA_RAYTRANSP))) {
930                         ma->texco |= NEED_UV|TEXCO_ORCO|TEXCO_REFL|TEXCO_NORM;
931                         if (r_mode & R_OSA) ma->texco |= TEXCO_OSA;
932                 }
933         }
934         
935         if (amb) {
936                 ma->ambr= ma->amb*amb[0];
937                 ma->ambg= ma->amb*amb[1];
938                 ma->ambb= ma->amb*amb[2];
939         }       
940         /* will become or-ed result of all node modes */
941         ma->mode_l= ma->mode;
942         ma->mode_l &= ~MA_SHLESS;
943
944         if (ma->strand_surfnor > 0.0f)
945                 ma->mode_l |= MA_STR_SURFDIFF;
946
947         /* parses the geom+tex nodes */
948         if (ma->nodetree && ma->use_nodes)
949                 ntreeShaderGetTexcoMode(ma->nodetree, r_mode, &ma->texco, &ma->mode_l);
950 }
951
952 static void init_render_nodetree(bNodeTree *ntree, Material *basemat, int r_mode, float *amb)
953 {
954         bNode *node;
955         
956         for (node=ntree->nodes.first; node; node= node->next) {
957                 if (node->id) {
958                         if (GS(node->id->name)==ID_MA) {
959                                 Material *ma= (Material *)node->id;
960                                 if (ma!=basemat) {
961                                         do_init_render_material(ma, r_mode, amb);
962                                         basemat->texco |= ma->texco;
963                                         basemat->mode_l |= ma->mode_l & ~(MA_TRANSP|MA_ZTRANSP|MA_RAYTRANSP); 
964                                 }
965                         }
966                         else if (node->type==NODE_GROUP)
967                                 init_render_nodetree((bNodeTree *)node->id, basemat, r_mode, amb);
968                 }
969         }
970 }
971
972 void init_render_material(Material *mat, int r_mode, float *amb)
973 {
974         
975         do_init_render_material(mat, r_mode, amb);
976         
977         if (mat->nodetree && mat->use_nodes) {
978                 init_render_nodetree(mat->nodetree, mat, r_mode, amb);
979                 
980                 if (!mat->nodetree->execdata)
981                         mat->nodetree->execdata = ntreeShaderBeginExecTree(mat->nodetree, 1);
982         }
983 }
984
985 void init_render_materials(Main *bmain, int r_mode, float *amb)
986 {
987         Material *ma;
988         
989         /* clear these flags before going over materials, to make sure they
990          * are cleared only once, otherwise node materials contained in other
991          * node materials can go wrong */
992         for (ma= bmain->mat.first; ma; ma= ma->id.next) {
993                 if (ma->id.us) {
994                         ma->texco= 0;
995                         ma->mapto= 0;
996                 }
997         }
998
999         /* two steps, first initialize, then or the flags for layers */
1000         for (ma= bmain->mat.first; ma; ma= ma->id.next) {
1001                 /* is_used flag comes back in convertblender.c */
1002                 ma->flag &= ~MA_IS_USED;
1003                 if (ma->id.us) 
1004                         init_render_material(ma, r_mode, amb);
1005         }
1006         
1007         do_init_render_material(&defmaterial, r_mode, amb);
1008 }
1009
1010 /* only needed for nodes now */
1011 void end_render_material(Material *mat)
1012 {
1013         if (mat && mat->nodetree && mat->use_nodes) {
1014                 if (mat->nodetree->execdata)
1015                         ntreeShaderEndExecTree(mat->nodetree->execdata, 1);
1016         }
1017 }
1018
1019 void end_render_materials(Main *bmain)
1020 {
1021         Material *ma;
1022         for (ma= bmain->mat.first; ma; ma= ma->id.next)
1023                 if (ma->id.us) 
1024                         end_render_material(ma);
1025 }
1026
1027 static int material_in_nodetree(bNodeTree *ntree, Material *mat)
1028 {
1029         bNode *node;
1030
1031         for (node=ntree->nodes.first; node; node= node->next) {
1032                 if (node->id && GS(node->id->name)==ID_MA) {
1033                         if (node->id==(ID*)mat)
1034                                 return 1;
1035                 }
1036                 else if (node->type==NODE_GROUP)
1037                         if (material_in_nodetree((bNodeTree*)node->id, mat))
1038                                 return 1;
1039         }
1040
1041         return 0;
1042 }
1043
1044 int material_in_material(Material *parmat, Material *mat)
1045 {
1046         if (parmat==mat)
1047                 return 1;
1048         else if (parmat->nodetree && parmat->use_nodes)
1049                 return material_in_nodetree(parmat->nodetree, mat);
1050         else
1051                 return 0;
1052 }
1053         
1054 /* ****************** */
1055 #if 0 /* UNUSED */
1056 static char colname_array[125][20]= {
1057 "Black", "DarkRed", "HalfRed", "Red", "Red",
1058 "DarkGreen", "DarkOlive", "Brown", "Chocolate", "OrangeRed",
1059 "HalfGreen", "GreenOlive", "DryOlive", "Goldenrod", "DarkOrange",
1060 "LightGreen", "Chartreuse", "YellowGreen", "Yellow", "Gold",
1061 "Green", "LawnGreen", "GreenYellow", "LightOlive", "Yellow",
1062 "DarkBlue", "DarkPurple", "HotPink", "VioletPink", "RedPink",
1063 "SlateGray", "DarkGrey", "PalePurple", "IndianRed", "Tomato",
1064 "SeaGreen", "PaleGreen", "GreenKhaki", "LightBrown", "LightSalmon",
1065 "SpringGreen", "PaleGreen", "MediumOlive", "YellowBrown", "LightGold",
1066 "LightGreen", "LightGreen", "LightGreen", "GreenYellow", "PaleYellow",
1067 "HalfBlue", "DarkSky", "HalfMagenta", "VioletRed", "DeepPink",
1068 "SteelBlue", "SkyBlue", "Orchid", "LightHotPink", "HotPink",
1069 "SeaGreen", "SlateGray", "MediumGrey", "Burlywood", "LightPink",
1070 "SpringGreen", "Aquamarine", "PaleGreen", "Khaki", "PaleOrange",
1071 "SpringGreen", "SeaGreen", "PaleGreen", "PaleWhite", "YellowWhite",
1072 "LightBlue", "Purple", "MediumOrchid", "Magenta", "Magenta",
1073 "RoyalBlue", "SlateBlue", "MediumOrchid", "Orchid", "Magenta",
1074 "DeepSkyBlue", "LightSteelBlue", "LightSkyBlue", "Violet", "LightPink",
1075 "Cyan", "DarkTurquoise", "SkyBlue", "Grey", "Snow",
1076 "Mint", "Mint", "Aquamarine", "MintCream", "Ivory",
1077 "Blue", "Blue", "DarkMagenta", "DarkOrchid", "Magenta",
1078 "SkyBlue", "RoyalBlue", "LightSlateBlue", "MediumOrchid", "Magenta",
1079 "DodgerBlue", "SteelBlue", "MediumPurple", "PalePurple", "Plum",
1080 "DeepSkyBlue", "PaleBlue", "LightSkyBlue", "PalePurple", "Thistle",
1081 "Cyan", "ColdBlue", "PaleTurquoise", "GhostWhite", "White"
1082 };
1083
1084 void automatname(Material *ma)
1085 {
1086         int nr, r, g, b;
1087         float ref;
1088         
1089         if (ma==NULL) return;
1090         if (ma->mode & MA_SHLESS) ref= 1.0;
1091         else ref= ma->ref;
1092         
1093         r= (int)(4.99f*(ref*ma->r));
1094         g= (int)(4.99f*(ref*ma->g));
1095         b= (int)(4.99f*(ref*ma->b));
1096         nr= r + 5*g + 25*b;
1097         if (nr>124) nr= 124;
1098         new_id(&G.main->mat, (ID *)ma, colname_array[nr]);
1099         
1100 }
1101 #endif
1102
1103 int object_remove_material_slot(Object *ob)
1104 {
1105         Material *mao, ***matarar;
1106         Object *obt;
1107         short *totcolp;
1108         short a, actcol;
1109         
1110         if (ob==NULL || ob->totcol==0) {
1111                 return FALSE;
1112         }
1113
1114         /* this should never happen and used to crash */
1115         if (ob->actcol <= 0) {
1116                 printf("%s: invalid material index %d, report a bug!\n", __func__, ob->actcol);
1117                 BLI_assert(0);
1118                 return FALSE;
1119         }
1120
1121         /* take a mesh/curve/mball as starting point, remove 1 index,
1122          * AND with all objects that share the ob->data
1123          * 
1124          * after that check indices in mesh/curve/mball!!!
1125          */
1126         
1127         totcolp= give_totcolp(ob);
1128         matarar= give_matarar(ob);
1129
1130         if (*matarar==NULL) return FALSE;
1131
1132         /* we delete the actcol */
1133         mao= (*matarar)[ob->actcol-1];
1134         if (mao) mao->id.us--;
1135         
1136         for (a=ob->actcol; a<ob->totcol; a++)
1137                 (*matarar)[a-1]= (*matarar)[a];
1138         (*totcolp)--;
1139         
1140         if (*totcolp==0) {
1141                 MEM_freeN(*matarar);
1142                 *matarar= NULL;
1143         }
1144         
1145         actcol= ob->actcol;
1146         obt= G.main->object.first;
1147         while (obt) {
1148         
1149                 if (obt->data==ob->data) {
1150                         
1151                         /* WATCH IT: do not use actcol from ob or from obt (can become zero) */
1152                         mao= obt->mat[actcol-1];
1153                         if (mao) mao->id.us--;
1154                 
1155                         for (a=actcol; a<obt->totcol; a++) {
1156                                 obt->mat[a-1]= obt->mat[a];
1157                                 obt->matbits[a-1]= obt->matbits[a];
1158                         }
1159                         obt->totcol--;
1160                         if (obt->actcol > obt->totcol) obt->actcol= obt->totcol;
1161                         
1162                         if (obt->totcol==0) {
1163                                 MEM_freeN(obt->mat);
1164                                 MEM_freeN(obt->matbits);
1165                                 obt->mat= NULL;
1166                                 obt->matbits= NULL;
1167                         }
1168                 }
1169                 obt= obt->id.next;
1170         }
1171
1172         /* check indices from mesh */
1173         if (ELEM4(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) {
1174                 data_delete_material_index_id((ID *)ob->data, actcol-1);
1175                 freedisplist(&ob->disp);
1176         }
1177
1178         return TRUE;
1179 }
1180
1181
1182 /* r_col = current value, col = new value, fac==0 is no change */
1183 void ramp_blend(int type, float r_col[3], const float fac, const float col[3])
1184 {
1185         float tmp, facm= 1.0f-fac;
1186         
1187         switch (type) {
1188                 case MA_RAMP_BLEND:
1189                         r_col[0] = facm*(r_col[0]) + fac*col[0];
1190                         r_col[1] = facm*(r_col[1]) + fac*col[1];
1191                         r_col[2] = facm*(r_col[2]) + fac*col[2];
1192                         break;
1193                 case MA_RAMP_ADD:
1194                         r_col[0] += fac*col[0];
1195                         r_col[1] += fac*col[1];
1196                         r_col[2] += fac*col[2];
1197                         break;
1198                 case MA_RAMP_MULT:
1199                         r_col[0] *= (facm + fac*col[0]);
1200                         r_col[1] *= (facm + fac*col[1]);
1201                         r_col[2] *= (facm + fac*col[2]);
1202                         break;
1203                 case MA_RAMP_SCREEN:
1204                         r_col[0] = 1.0f - (facm + fac*(1.0f - col[0])) * (1.0f - r_col[0]);
1205                         r_col[1] = 1.0f - (facm + fac*(1.0f - col[1])) * (1.0f - r_col[1]);
1206                         r_col[2] = 1.0f - (facm + fac*(1.0f - col[2])) * (1.0f - r_col[2]);
1207                         break;
1208                 case MA_RAMP_OVERLAY:
1209                         if (r_col[0] < 0.5f)
1210                                 r_col[0] *= (facm + 2.0f*fac*col[0]);
1211                         else
1212                                 r_col[0] = 1.0f - (facm + 2.0f*fac*(1.0f - col[0])) * (1.0f - r_col[0]);
1213                         if (r_col[1] < 0.5f)
1214                                 r_col[1] *= (facm + 2.0f*fac*col[1]);
1215                         else
1216                                 r_col[1] = 1.0f - (facm + 2.0f*fac*(1.0f - col[1])) * (1.0f - r_col[1]);
1217                         if (r_col[2] < 0.5f)
1218                                 r_col[2] *= (facm + 2.0f*fac*col[2]);
1219                         else
1220                                 r_col[2] = 1.0f - (facm + 2.0f*fac*(1.0f - col[2])) * (1.0f - r_col[2]);
1221                         break;
1222                 case MA_RAMP_SUB:
1223                         r_col[0] -= fac*col[0];
1224                         r_col[1] -= fac*col[1];
1225                         r_col[2] -= fac*col[2];
1226                         break;
1227                 case MA_RAMP_DIV:
1228                         if (col[0]!=0.0f)
1229                                 r_col[0] = facm*(r_col[0]) + fac*(r_col[0])/col[0];
1230                         if (col[1]!=0.0f)
1231                                 r_col[1] = facm*(r_col[1]) + fac*(r_col[1])/col[1];
1232                         if (col[2]!=0.0f)
1233                                 r_col[2] = facm*(r_col[2]) + fac*(r_col[2])/col[2];
1234                         break;
1235                 case MA_RAMP_DIFF:
1236                         r_col[0] = facm*(r_col[0]) + fac*fabsf(r_col[0]-col[0]);
1237                         r_col[1] = facm*(r_col[1]) + fac*fabsf(r_col[1]-col[1]);
1238                         r_col[2] = facm*(r_col[2]) + fac*fabsf(r_col[2]-col[2]);
1239                         break;
1240                 case MA_RAMP_DARK:
1241                         tmp=col[0]+((1-col[0])*facm);
1242                         if (tmp < r_col[0]) r_col[0]= tmp;
1243                         tmp=col[1]+((1-col[1])*facm);
1244                         if (tmp < r_col[1]) r_col[1]= tmp;
1245                         tmp=col[2]+((1-col[2])*facm);
1246                         if (tmp < r_col[2]) r_col[2]= tmp;
1247                         break;
1248                 case MA_RAMP_LIGHT:
1249                         tmp= fac*col[0];
1250                         if (tmp > r_col[0]) r_col[0]= tmp;
1251                                 tmp= fac*col[1];
1252                                 if (tmp > r_col[1]) r_col[1]= tmp;
1253                                 tmp= fac*col[2];
1254                                 if (tmp > r_col[2]) r_col[2]= tmp;
1255                                 break;
1256                 case MA_RAMP_DODGE:
1257                         if (r_col[0] != 0.0f) {
1258                                 tmp = 1.0f - fac*col[0];
1259                                 if (tmp <= 0.0f)
1260                                         r_col[0] = 1.0f;
1261                                 else if ((tmp = (r_col[0]) / tmp)> 1.0f)
1262                                         r_col[0] = 1.0f;
1263                                 else
1264                                         r_col[0] = tmp;
1265                         }
1266                         if (r_col[1] != 0.0f) {
1267                                 tmp = 1.0f - fac*col[1];
1268                                 if (tmp <= 0.0f )
1269                                         r_col[1] = 1.0f;
1270                                 else if ((tmp = (r_col[1]) / tmp) > 1.0f )
1271                                         r_col[1] = 1.0f;
1272                                 else
1273                                         r_col[1] = tmp;
1274                         }
1275                         if (r_col[2] != 0.0f) {
1276                                 tmp = 1.0f - fac*col[2];
1277                                 if (tmp <= 0.0f)
1278                                         r_col[2] = 1.0f;
1279                                 else if ((tmp = (r_col[2]) / tmp) > 1.0f )
1280                                         r_col[2] = 1.0f;
1281                                 else
1282                                         r_col[2] = tmp;
1283                         }
1284                         break;
1285                 case MA_RAMP_BURN:
1286                         tmp = facm + fac*col[0];
1287
1288                         if (tmp <= 0.0f)
1289                                 r_col[0] = 0.0f;
1290                         else if (( tmp = (1.0f - (1.0f - (r_col[0])) / tmp )) < 0.0f)
1291                                         r_col[0] = 0.0f;
1292                         else if (tmp > 1.0f)
1293                                 r_col[0]=1.0f;
1294                         else
1295                                 r_col[0] = tmp;
1296
1297                         tmp = facm + fac*col[1];
1298                         if (tmp <= 0.0f)
1299                                 r_col[1] = 0.0f;
1300                         else if (( tmp = (1.0f - (1.0f - (r_col[1])) / tmp )) < 0.0f )
1301                                         r_col[1] = 0.0f;
1302                         else if (tmp >1.0f)
1303                                 r_col[1]=1.0f;
1304                         else
1305                                 r_col[1] = tmp;
1306
1307                                 tmp = facm + fac*col[2];
1308                                 if (tmp <= 0.0f)
1309                                 r_col[2] = 0.0f;
1310                         else if (( tmp = (1.0f - (1.0f - (r_col[2])) / tmp )) < 0.0f  )
1311                                         r_col[2] = 0.0f;
1312                         else if (tmp >1.0f)
1313                                 r_col[2]= 1.0f;
1314                         else
1315                                 r_col[2] = tmp;
1316                         break;
1317                 case MA_RAMP_HUE:
1318                         {
1319                                 float rH, rS, rV;
1320                                 float colH, colS, colV;
1321                                 float tmpr, tmpg, tmpb;
1322                                 rgb_to_hsv(col[0], col[1], col[2], &colH, &colS, &colV);
1323                                 if (colS != 0) {
1324                                         rgb_to_hsv(r_col[0], r_col[1], r_col[2], &rH, &rS, &rV);
1325                                         hsv_to_rgb(colH, rS, rV, &tmpr, &tmpg, &tmpb);
1326                                         r_col[0] = facm*(r_col[0]) + fac*tmpr;
1327                                         r_col[1] = facm*(r_col[1]) + fac*tmpg;
1328                                         r_col[2] = facm*(r_col[2]) + fac*tmpb;
1329                                 }
1330                         }
1331                         break;
1332                 case MA_RAMP_SAT:
1333                         {
1334                                 float rH, rS, rV;
1335                                 float colH, colS, colV;
1336                                 rgb_to_hsv(r_col[0], r_col[1], r_col[2], &rH, &rS, &rV);
1337                                 if (rS != 0) {
1338                                         rgb_to_hsv(col[0], col[1], col[2], &colH, &colS, &colV);
1339                                         hsv_to_rgb(rH, (facm*rS +fac*colS), rV, r_col+0, r_col+1, r_col+2);
1340                                 }
1341                         }
1342                         break;
1343                 case MA_RAMP_VAL:
1344                         {
1345                                 float rH, rS, rV;
1346                                 float colH, colS, colV;
1347                                 rgb_to_hsv(r_col[0], r_col[1], r_col[2], &rH, &rS, &rV);
1348                                 rgb_to_hsv(col[0], col[1], col[2], &colH, &colS, &colV);
1349                                 hsv_to_rgb(rH, rS, (facm*rV +fac*colV), r_col+0, r_col+1, r_col+2);
1350                         }
1351                         break;
1352                 case MA_RAMP_COLOR:
1353                         {
1354                                 float rH, rS, rV;
1355                                 float colH, colS, colV;
1356                                 float tmpr, tmpg, tmpb;
1357                                 rgb_to_hsv(col[0], col[1], col[2], &colH, &colS, &colV);
1358                                 if (colS != 0) {
1359                                         rgb_to_hsv(r_col[0], r_col[1], r_col[2], &rH, &rS, &rV);
1360                                         hsv_to_rgb(colH, colS, rV, &tmpr, &tmpg, &tmpb);
1361                                         r_col[0] = facm*(r_col[0]) + fac*tmpr;
1362                                         r_col[1] = facm*(r_col[1]) + fac*tmpg;
1363                                         r_col[2] = facm*(r_col[2]) + fac*tmpb;
1364                                 }
1365                         }
1366                         break;
1367                 case MA_RAMP_SOFT:
1368                         {
1369                                 float scr, scg, scb;
1370
1371                                 /* first calculate non-fac based Screen mix */
1372                                 scr = 1.0f - (1.0f - col[0]) * (1.0f - r_col[0]);
1373                                 scg = 1.0f - (1.0f - col[1]) * (1.0f - r_col[1]);
1374                                 scb = 1.0f - (1.0f - col[2]) * (1.0f - r_col[2]);
1375
1376                                 r_col[0] = facm*(r_col[0]) + fac*(((1.0f - r_col[0]) * col[0] * (r_col[0])) + (r_col[0] * scr));
1377                                 r_col[1] = facm*(r_col[1]) + fac*(((1.0f - r_col[1]) * col[1] * (r_col[1])) + (r_col[1] * scg));
1378                                 r_col[2] = facm*(r_col[2]) + fac*(((1.0f - r_col[2]) * col[2] * (r_col[2])) + (r_col[2] * scb));
1379                         }
1380                         break;
1381                 case MA_RAMP_LINEAR:
1382                         if (col[0] > 0.5f)
1383                                 r_col[0] = r_col[0] + fac*(2.0f*(col[0]-0.5f));
1384                         else
1385                                 r_col[0] = r_col[0] + fac*(2.0f*(col[0]) - 1.0f);
1386                         if (col[1] > 0.5f)
1387                                 r_col[1] = r_col[1] + fac*(2.0f*(col[1]-0.5f));
1388                         else
1389                                 r_col[1] = r_col[1] + fac*(2.0f*(col[1]) -1.0f);
1390                         if (col[2] > 0.5f)
1391                                 r_col[2] = r_col[2] + fac*(2.0f*(col[2]-0.5f));
1392                         else
1393                                 r_col[2] = r_col[2] + fac*(2.0f*(col[2]) - 1.0f);
1394                         break;
1395         }
1396 }
1397
1398 /* copy/paste buffer, if we had a propper py api that would be better */
1399 static Material matcopybuf;
1400 static short matcopied= 0;
1401
1402 void clear_matcopybuf(void)
1403 {
1404         memset(&matcopybuf, 0, sizeof(Material));
1405         matcopied= 0;
1406 }
1407
1408 void free_matcopybuf(void)
1409 {
1410         int a;
1411
1412         for (a=0; a<MAX_MTEX; a++) {
1413                 if (matcopybuf.mtex[a]) {
1414                         MEM_freeN(matcopybuf.mtex[a]);
1415                         matcopybuf.mtex[a]= NULL;
1416                 }
1417         }
1418
1419         if (matcopybuf.ramp_col) MEM_freeN(matcopybuf.ramp_col);
1420         if (matcopybuf.ramp_spec) MEM_freeN(matcopybuf.ramp_spec);
1421
1422         matcopybuf.ramp_col= NULL;
1423         matcopybuf.ramp_spec= NULL;
1424
1425         if (matcopybuf.nodetree) {
1426                 ntreeFreeTree(matcopybuf.nodetree);
1427                 MEM_freeN(matcopybuf.nodetree);
1428                 matcopybuf.nodetree= NULL;
1429         }
1430
1431         matcopied= 0;
1432 }
1433
1434 void copy_matcopybuf(Material *ma)
1435 {
1436         int a;
1437         MTex *mtex;
1438
1439         if (matcopied)
1440                 free_matcopybuf();
1441
1442         memcpy(&matcopybuf, ma, sizeof(Material));
1443         if (matcopybuf.ramp_col) matcopybuf.ramp_col= MEM_dupallocN(matcopybuf.ramp_col);
1444         if (matcopybuf.ramp_spec) matcopybuf.ramp_spec= MEM_dupallocN(matcopybuf.ramp_spec);
1445
1446         for (a=0; a<MAX_MTEX; a++) {
1447                 mtex= matcopybuf.mtex[a];
1448                 if (mtex) {
1449                         matcopybuf.mtex[a]= MEM_dupallocN(mtex);
1450                 }
1451         }
1452         matcopybuf.nodetree= ntreeCopyTree(ma->nodetree);
1453         matcopybuf.preview= NULL;
1454         matcopybuf.gpumaterial.first= matcopybuf.gpumaterial.last= NULL;
1455         matcopied= 1;
1456 }
1457
1458 void paste_matcopybuf(Material *ma)
1459 {
1460         int a;
1461         MTex *mtex;
1462         ID id;
1463
1464         if (matcopied==0)
1465                 return;
1466         /* free current mat */
1467         if (ma->ramp_col) MEM_freeN(ma->ramp_col);
1468         if (ma->ramp_spec) MEM_freeN(ma->ramp_spec);
1469         for (a=0; a<MAX_MTEX; a++) {
1470                 mtex= ma->mtex[a];
1471                 if (mtex && mtex->tex) mtex->tex->id.us--;
1472                 if (mtex) MEM_freeN(mtex);
1473         }
1474
1475         if (ma->nodetree) {
1476                 ntreeFreeTree(ma->nodetree);
1477                 MEM_freeN(ma->nodetree);
1478         }
1479
1480         GPU_material_free(ma);
1481
1482         id= (ma->id);
1483         memcpy(ma, &matcopybuf, sizeof(Material));
1484         (ma->id)= id;
1485
1486         if (matcopybuf.ramp_col) ma->ramp_col= MEM_dupallocN(matcopybuf.ramp_col);
1487         if (matcopybuf.ramp_spec) ma->ramp_spec= MEM_dupallocN(matcopybuf.ramp_spec);
1488
1489         for (a=0; a<MAX_MTEX; a++) {
1490                 mtex= ma->mtex[a];
1491                 if (mtex) {
1492                         ma->mtex[a]= MEM_dupallocN(mtex);
1493                         if (mtex->tex) id_us_plus((ID *)mtex->tex);
1494                 }
1495         }
1496
1497         ma->nodetree= ntreeCopyTree(matcopybuf.nodetree);
1498 }
1499
1500
1501 /*********************** texface to material convert functions **********************/
1502 /* encode all the TF information into a single int */
1503 static int encode_tfaceflag(MTFace *tf, int convertall)
1504 {
1505         /* calculate the flag */
1506         int flag = tf->mode;
1507
1508         /* options that change the material offline render */   
1509         if (!convertall) {
1510                 flag &= ~TF_OBCOL;
1511         }
1512
1513         /* clean flags that are not being converted */
1514         flag &= ~TF_TEX;
1515         flag &= ~TF_SHAREDVERT;
1516         flag &= ~TF_SHAREDCOL;
1517         flag &= ~TF_CONVERTED;
1518
1519         /* light tface flag is ignored in GLSL mode */
1520         flag &= ~TF_LIGHT;
1521         
1522         /* 15 is how big the flag can be - hardcoded here and in decode_tfaceflag() */
1523         flag |= tf->transp << 15;
1524         
1525         /* increase 1 so flag 0 is different than no flag yet */
1526         return flag + 1;
1527 }
1528
1529 /* set the material options based in the tface flag */
1530 static void decode_tfaceflag(Material *ma, int flag, int convertall)
1531 {
1532         int alphablend; 
1533         GameSettings *game= &ma->game;
1534
1535         /* flag is shifted in 1 to make 0 != no flag yet (see encode_tfaceflag) */
1536         flag -= 1;
1537
1538         alphablend = flag >> 15; //encoded in the encode_tfaceflag function
1539         (*game).flag = 0;
1540         
1541         /* General Material Options */
1542         if ((flag & TF_DYNAMIC)==0) (*game).flag        |= GEMAT_NOPHYSICS;
1543         
1544         /* Material Offline Rendering Properties */
1545         if (convertall) {
1546                 if (flag & TF_OBCOL) ma->shade_flag |= MA_OBCOLOR;
1547         }
1548         
1549         /* Special Face Properties */
1550         if ((flag & TF_TWOSIDE)==0) (*game).flag |= GEMAT_BACKCULL;
1551         if (flag & TF_INVISIBLE)(*game).flag |= GEMAT_INVISIBLE;
1552         if (flag & TF_BMFONT) (*game).flag |= GEMAT_TEXT;
1553         
1554         /* Face Orientation */
1555         if (flag & TF_BILLBOARD) (*game).face_orientation |= GEMAT_HALO;
1556         else if (flag & TF_BILLBOARD2) (*game).face_orientation |= GEMAT_BILLBOARD;
1557         else if (flag & TF_SHADOW) (*game).face_orientation |= GEMAT_SHADOW;
1558         
1559         /* Alpha Blend */
1560         if (flag & TF_ALPHASORT && ELEM(alphablend, TF_ALPHA, TF_ADD)) (*game).alpha_blend = GEMAT_ALPHA_SORT;
1561         else if (alphablend & TF_ALPHA) (*game).alpha_blend = GEMAT_ALPHA;
1562         else if (alphablend & TF_ADD) (*game).alpha_blend = GEMAT_ADD;
1563         else if (alphablend & TF_CLIP) (*game).alpha_blend = GEMAT_CLIP;
1564 }
1565
1566 /* boolean check to see if the mesh needs a material */
1567 static int check_tfaceneedmaterial(int flag)
1568 {
1569         // check if the flags we have are not deprecated != than default material options
1570         // also if only flags are visible and collision see if all objects using this mesh have this option in physics
1571
1572         /* flag is shifted in 1 to make 0 != no flag yet (see encode_tfaceflag) */
1573         flag -=1;
1574
1575         // deprecated flags
1576         flag &= ~TF_OBCOL;
1577         flag &= ~TF_SHAREDVERT;
1578         flag &= ~TF_SHAREDCOL;
1579
1580         /* light tface flag is ignored in GLSL mode */
1581         flag &= ~TF_LIGHT;
1582         
1583         // automatic detected if tex image has alpha
1584         flag &= ~(TF_ALPHA << 15);
1585         // automatic detected if using texture
1586         flag &= ~TF_TEX;
1587
1588         // settings for the default NoMaterial
1589         if (flag == TF_DYNAMIC)
1590                 return 0;
1591
1592         else
1593                 return 1;
1594 }
1595
1596 /* return number of digits of an integer */
1597 // XXX to be optmized or replaced by an equivalent blender internal function
1598 static int integer_getdigits(int number)
1599 {
1600         int i=0;
1601         if (number == 0) return 1;
1602
1603         while (number != 0) {
1604                 number = (int)(number/10);
1605                 i++;
1606         }
1607         return i;
1608 }
1609
1610 static void calculate_tface_materialname(char *matname, char *newname, int flag)
1611 {
1612         // if flag has only light and collision and material matches those values
1613         // you can do strcpy(name, mat_name);
1614         // otherwise do:
1615         int digits = integer_getdigits(flag);
1616         /* clamp the old name, remove the MA prefix and add the .TF.flag suffix
1617          * e.g. matname = "MALoooooooooooooongName"; newname = "Loooooooooooooon.TF.2" */
1618         BLI_snprintf(newname, MAX_ID_NAME, "%.*s.TF.%0*d", MAX_ID_NAME-(digits+5), matname, digits, flag);
1619 }
1620
1621 /* returns -1 if no match */
1622 static short mesh_getmaterialnumber(Mesh *me, Material *ma)
1623 {
1624         short a;
1625
1626         for (a=0; a<me->totcol; a++) {
1627                 if (me->mat[a] == ma) {
1628                         return a;
1629                 }
1630         }
1631
1632         return -1;
1633 }
1634
1635 /* append material */
1636 static short mesh_addmaterial(Mesh *me, Material *ma)
1637 {
1638         material_append_id(&me->id, NULL);
1639         me->mat[me->totcol-1]= ma;
1640
1641         id_us_plus(&ma->id);
1642
1643         return me->totcol-1;
1644 }
1645
1646 static void set_facetexture_flags(Material *ma, Image *image)
1647 {
1648         if (image) {
1649                 ma->mode |= MA_FACETEXTURE;
1650                 /* we could check if the texture has alpha, but then more meshes sharing the same
1651                  * material may need it. Let's make it simple. */
1652                 if (BKE_image_has_alpha(image))
1653                         ma->mode |= MA_FACETEXTURE_ALPHA;
1654         }
1655 }
1656
1657 /* returns material number */
1658 static short convert_tfacenomaterial(Main *main, Mesh *me, MTFace *tf, int flag)
1659 {
1660         Material *ma;
1661         char idname[MAX_ID_NAME];
1662         short mat_nr= -1;
1663         
1664         /* new material, the name uses the flag*/
1665         BLI_snprintf(idname, sizeof(idname), "MAMaterial.TF.%0*d", integer_getdigits(flag), flag);
1666
1667         if ((ma= BLI_findstring(&main->mat, idname+2, offsetof(ID, name)+2))) {
1668                 mat_nr= mesh_getmaterialnumber(me, ma);
1669                 /* assign the material to the mesh */
1670                 if (mat_nr == -1) mat_nr= mesh_addmaterial(me, ma);
1671
1672                 /* if needed set "Face Textures [Alpha]" Material options */
1673                 set_facetexture_flags(ma, tf->tpage);
1674         }
1675         /* create a new material */
1676         else {
1677                 ma= add_material(idname+2);
1678
1679                 if (ma) {
1680                         printf("TexFace Convert: Material \"%s\" created.\n", idname+2);
1681                         mat_nr= mesh_addmaterial(me, ma);
1682                         
1683                         /* if needed set "Face Textures [Alpha]" Material options */
1684                         set_facetexture_flags(ma, tf->tpage);
1685
1686                         decode_tfaceflag(ma, flag, 1);
1687                         // the final decoding will happen after, outside the main loop
1688                         // for now store the flag into the material and change light/tex/collision 
1689                         // store the flag as a negative number
1690                         ma->game.flag = -flag;
1691                         id_us_min((ID *)ma);    
1692                 }
1693                 else printf("Error: Unable to create Material \"%s\" for Mesh \"%s\".", idname+2, me->id.name+2);
1694         }
1695
1696         /* set as converted, no need to go bad to this face */
1697         tf->mode |= TF_CONVERTED;       
1698         return mat_nr;
1699 }
1700
1701 /* Function to fully convert materials */
1702 static void convert_tfacematerial(Main *main, Material *ma)
1703 {
1704         Mesh *me;
1705         Material *mat_new;
1706         MFace *mf;
1707         MTFace *tf;
1708         int flag, index;
1709         int a;
1710         short mat_nr;
1711         CustomDataLayer *cdl;
1712         char idname[MAX_ID_NAME];
1713
1714         for (me=main->mesh.first; me; me=me->id.next) {
1715                 /* check if this mesh uses this material */
1716                 for (a=0;a<me->totcol;a++)
1717                         if (me->mat[a] == ma) break;
1718                         
1719                 /* no material found */
1720                 if (a == me->totcol) continue;
1721
1722                 /* get the active tface layer */
1723                 index= CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
1724                 cdl= (index == -1)? NULL: &me->fdata.layers[index];
1725                 if (!cdl) continue;
1726
1727                 /* loop over all the faces and stop at the ones that use the material*/
1728                 for (a=0, mf=me->mface; a<me->totface; a++, mf++) {
1729                         if (me->mat[mf->mat_nr] != ma) continue;
1730
1731                         /* texface data for this face */
1732                         tf = ((MTFace*)cdl->data) + a;
1733                         flag = encode_tfaceflag(tf, 1);
1734
1735                         /* the name of the new material */
1736                         calculate_tface_materialname(ma->id.name, (char *)&idname, flag);
1737
1738                         if ((mat_new= BLI_findstring(&main->mat, idname+2, offsetof(ID, name)+2))) {
1739                                 /* material already existent, see if the mesh has it */
1740                                 mat_nr = mesh_getmaterialnumber(me, mat_new);
1741                                 /* material is not in the mesh, add it */
1742                                 if (mat_nr == -1) mat_nr= mesh_addmaterial(me, mat_new);
1743                         }
1744                         /* create a new material */
1745                         else {
1746                                 mat_new=copy_material(ma);
1747                                 if (mat_new) {
1748                                         /* rename the material*/
1749                                         strcpy(mat_new->id.name, idname);
1750                                         id_us_min((ID *)mat_new);       
1751
1752                                         mat_nr= mesh_addmaterial(me, mat_new);
1753                                         decode_tfaceflag(mat_new, flag, 1);
1754                                 }
1755                                 else {
1756                                         printf("Error: Unable to create Material \"%s\" for Mesh \"%s.", idname+2, me->id.name+2);
1757                                         mat_nr = mf->mat_nr;
1758                                         continue;
1759                                 }
1760                         }
1761                         
1762                         /* if the material has a texture but no texture channel
1763                          * set "Face Textures [Alpha]" Material options 
1764                          * actually we need to run it always, because of old behavior
1765                          * of using face texture if any texture channel was present (multitex) */
1766                         //if ((!mat_new->mtex[0]) && (!mat_new->mtex[0]->tex))
1767                         set_facetexture_flags(mat_new, tf->tpage);
1768
1769                         /* set the material number to the face*/
1770                         mf->mat_nr = mat_nr;
1771                 }
1772                 /* remove material from mesh */
1773                 for (a=0;a<me->totcol;)
1774                         if (me->mat[a] == ma) material_pop_id(&me->id, a, 1);else a++;
1775         }
1776 }
1777
1778
1779 #define MAT_BGE_DISPUTED -99999
1780
1781 int do_version_tface(Main *main, int fileload)
1782 {
1783         Mesh *me;
1784         Material *ma;
1785         MFace *mf;
1786         MTFace *tf;
1787         CustomDataLayer *cdl;
1788         int a;
1789         int flag;
1790         int index;
1791
1792         /* sometimes mesh has no materials but will need a new one. In those
1793          * cases we need to ignore the mf->mat_nr and only look at the face
1794          * mode because it can be zero as uninitialized or the 1st created material
1795          */
1796         int nomaterialslots;
1797
1798         /* alert to user to check the console */
1799         int nowarning = 1;
1800
1801         /* mark all the materials to conversion with a flag
1802          * if there is tface create a complete flag for that storing in flag
1803          * if there is tface and flag > 0: creates a new flag based on this face
1804          * if flags are different set flag to -1  
1805          */
1806         
1807         /* 1st part: marking mesh materials to update */
1808         for (me=main->mesh.first; me; me=me->id.next) {
1809                 if (me->id.lib) continue;
1810
1811                 /* get the active tface layer */
1812                 index= CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
1813                 cdl= (index == -1)? NULL: &me->fdata.layers[index];
1814                 if (!cdl) continue;
1815
1816                 nomaterialslots = (me->totcol==0?1:0);
1817                 
1818                 /* loop over all the faces*/
1819                 for (a=0, mf=me->mface; a<me->totface; a++, mf++) {
1820                         /* texface data for this face */
1821                         tf = ((MTFace*)cdl->data) + a;
1822
1823                         /* conversion should happen only once */
1824                         if (fileload)
1825                                 tf->mode &= ~TF_CONVERTED;
1826                         else {
1827                                 if ((tf->mode & TF_CONVERTED)) continue;
1828                                 else tf->mode |= TF_CONVERTED;
1829                         }
1830                         
1831                         /* no material slots */
1832                         if (nomaterialslots) {
1833                                 flag = encode_tfaceflag(tf, 1);
1834                                 
1835                                 /* create/find a new material and assign to the face */
1836                                 if (check_tfaceneedmaterial(flag)) {
1837                                         mf->mat_nr= convert_tfacenomaterial(main, me, tf, flag);
1838                                 }
1839                                 /* else mark them as no-material to be reverted to 0 later */
1840                                 else {
1841                                         mf->mat_nr = -1;
1842                                 }
1843                         }
1844                         else if (mf->mat_nr < me->totcol) {
1845                                 ma= me->mat[mf->mat_nr];
1846                                 
1847                                 /* no material create one if necessary */
1848                                 if (!ma) {
1849                                         /* find a new material and assign to the face */
1850                                         flag = encode_tfaceflag(tf, 1);
1851
1852                                         /* create/find a new material and assign to the face */
1853                                         if (check_tfaceneedmaterial(flag))
1854                                                 mf->mat_nr= convert_tfacenomaterial(main, me, tf, flag);
1855
1856                                         continue;
1857                                 }
1858
1859                                 /* we can't read from this if it comes from a library,
1860                                  * at doversion time: direct_link might not have happened on it,
1861                                  * so ma->mtex is not pointing to valid memory yet.
1862                                  * later we could, but it's better not */
1863                                 else if (ma->id.lib)
1864                                         continue;
1865                                 
1866                                 /* material already marked as disputed */
1867                                 else if (ma->game.flag == MAT_BGE_DISPUTED)
1868                                         continue;
1869
1870                                 /* found a material */
1871                                 else {
1872                                         flag = encode_tfaceflag(tf, ((fileload)?0:1));
1873
1874                                         /* first time changing this material */
1875                                         if (ma->game.flag == 0)
1876                                                 ma->game.flag= -flag;
1877                         
1878                                         /* mark material as disputed */
1879                                         else if (ma->game.flag != -flag) {
1880                                                 ma->game.flag = MAT_BGE_DISPUTED;
1881                                                 continue;
1882                                         }
1883                         
1884                                         /* material ok so far */
1885                                         else {
1886                                                 ma->game.flag = -flag;
1887                                                 
1888                                                 /* some people uses multitexture with TexFace by creating a texture
1889                                                  * channel which not necessarily the tf->tpage image. But the game engine
1890                                                  * was enabling it. Now it's required to set "Face Texture [Alpha] in the
1891                                                  * material settings. */
1892                                                 if (!fileload)
1893                                                         set_facetexture_flags(ma, tf->tpage);
1894                                         }
1895                                 }
1896                         }
1897                         else {
1898                                 continue;
1899                         }
1900                 }
1901
1902                 /* if we didn't have material slot and now we do, we need to
1903                  * make sure the materials are correct */
1904                 if (nomaterialslots) {
1905                         if (me->totcol>0) {
1906                                 for (a=0, mf=me->mface; a<me->totface; a++, mf++) {
1907                                         if (mf->mat_nr == -1) {
1908                                                 /* texface data for this face */
1909                                                 tf = ((MTFace*)cdl->data) + a;
1910                                                 mf->mat_nr= convert_tfacenomaterial(main, me, tf, encode_tfaceflag(tf, 1));
1911                                         }
1912                                 }
1913                         }
1914                         else {
1915                                 for (a=0, mf=me->mface; a<me->totface; a++, mf++) {
1916                                         mf->mat_nr=0;
1917                                 }
1918                         }
1919                 }
1920
1921         }
1922         
1923         /* 2nd part - conversion */
1924         /* skip library files */
1925
1926         /* we shouldn't loop through the materials created in the loop. make the loop stop at its original length) */
1927         for (ma= main->mat.first, a=0; ma; ma= ma->id.next, a++) {
1928                 if (ma->id.lib) continue;
1929
1930                 /* disputed material */
1931                 if (ma->game.flag == MAT_BGE_DISPUTED) {
1932                         ma->game.flag = 0;
1933                         if (fileload) {
1934                                 printf("Warning: material \"%s\" skipped - to convert old game texface to material go to the Help menu.\n", ma->id.name+2);
1935                                 nowarning = 0;
1936                         }
1937                         else
1938                                 convert_tfacematerial(main, ma);
1939                         continue;       
1940                 }
1941         
1942                 /* no conflicts in this material - 90% of cases
1943                  * convert from tface system to material */
1944                 else if (ma->game.flag < 0) {
1945                         decode_tfaceflag(ma, -(ma->game.flag), 1);
1946
1947                         /* material is good make sure all faces using
1948                          * this material are set to converted */
1949                         if (fileload) {
1950                                 for (me=main->mesh.first; me; me=me->id.next) {
1951                                         /* check if this mesh uses this material */
1952                                         for (a=0;a<me->totcol;a++)
1953                                                 if (me->mat[a] == ma) break;
1954                                                 
1955                                         /* no material found */
1956                                         if (a == me->totcol) continue;
1957                         
1958                                         /* get the active tface layer */
1959                                         index= CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
1960                                         cdl= (index == -1)? NULL: &me->fdata.layers[index];
1961                                         if (!cdl) continue;
1962                         
1963                                         /* loop over all the faces and stop at the ones that use the material*/
1964                                         for (a=0, mf=me->mface; a<me->totface; a++, mf++) {
1965                                                 if (me->mat[mf->mat_nr] == ma) {
1966                                                         /* texface data for this face */
1967                                                         tf = ((MTFace*)cdl->data) + a;
1968                                                         tf->mode |= TF_CONVERTED;
1969                                                 }
1970                                         }
1971                                 }
1972                         }
1973                 }
1974                 /* material is not used by faces with texface
1975                  * set the default flag - do it only once */
1976                 else {
1977                         if (fileload) {
1978                                 ma->game.flag = GEMAT_BACKCULL;
1979                         }
1980                 }
1981         }
1982
1983         return nowarning;
1984 }
1985