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