style cleanup: switch statements, include break statements within braces & indent.
[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         ma->vcol_alpha = 0;
157         
158         ma->gloss_mir = ma->gloss_tra = 1.0;
159         ma->samp_gloss_mir = ma->samp_gloss_tra = 18;
160         ma->adapt_thresh_mir = ma->adapt_thresh_tra = 0.005;
161         ma->dist_mir = 0.0;
162         ma->fadeto_mir = MA_RAYMIR_FADETOSKY;
163         
164         ma->rampfac_col = 1.0;
165         ma->rampfac_spec = 1.0;
166         ma->pr_lamp = 3;         /* two lamps, is bits */
167         ma->pr_type = MA_SPHERE;
168
169         ma->sss_radius[0] = 1.0f;
170         ma->sss_radius[1] = 1.0f;
171         ma->sss_radius[2] = 1.0f;
172         ma->sss_col[0] = 1.0f;
173         ma->sss_col[1] = 1.0f;
174         ma->sss_col[2] = 1.0f;
175         ma->sss_error = 0.05f;
176         ma->sss_scale = 0.1f;
177         ma->sss_ior = 1.3f;
178         ma->sss_colfac = 1.0f;
179         ma->sss_texfac = 0.0f;
180         ma->sss_front = 1.0f;
181         ma->sss_back = 1.0f;
182
183         ma->vol.density = 1.0f;
184         ma->vol.emission = 0.0f;
185         ma->vol.scattering = 1.0f;
186         ma->vol.reflection = 1.0f;
187         ma->vol.transmission_col[0] = ma->vol.transmission_col[1] = ma->vol.transmission_col[2] = 1.0f;
188         ma->vol.reflection_col[0] = ma->vol.reflection_col[1] = ma->vol.reflection_col[2] = 1.0f;
189         ma->vol.emission_col[0] = ma->vol.emission_col[1] = ma->vol.emission_col[2] = 1.0f;
190         ma->vol.density_scale = 1.0f;
191         ma->vol.depth_cutoff = 0.01f;
192         ma->vol.stepsize_type = MA_VOL_STEP_RANDOMIZED;
193         ma->vol.stepsize = 0.2f;
194         ma->vol.shade_type = MA_VOL_SHADE_SHADED;
195         ma->vol.shadeflag |= MA_VOL_PRECACHESHADING;
196         ma->vol.precache_resolution = 50;
197         ma->vol.ms_spread = 0.2f;
198         ma->vol.ms_diff = 1.f;
199         ma->vol.ms_intensity = 1.f;
200         
201         ma->game.flag = GEMAT_BACKCULL;
202         ma->game.alpha_blend = 0;
203         ma->game.face_orientation = 0;
204         
205         ma->mode = MA_TRACEBLE | MA_SHADBUF | MA_SHADOW | MA_RAYBIAS | MA_TANGENT_STR | MA_ZTRANSP;
206         ma->shade_flag = MA_APPROX_OCCLUSION;
207         ma->preview = NULL;
208 }
209
210 Material *BKE_material_add(Main *bmain, const char *name)
211 {
212         Material *ma;
213
214         ma = BKE_libblock_alloc(&bmain->mat, ID_MA, name);
215         
216         init_material(ma);
217         
218         return ma;
219 }
220
221 /* XXX keep synced with next function */
222 Material *BKE_material_copy(Material *ma)
223 {
224         Material *man;
225         int a;
226         
227         man = BKE_libblock_copy(&ma->id);
228         
229         id_lib_extern((ID *)man->group);
230         
231         for (a = 0; a < MAX_MTEX; a++) {
232                 if (ma->mtex[a]) {
233                         man->mtex[a] = MEM_mallocN(sizeof(MTex), "copymaterial");
234                         memcpy(man->mtex[a], ma->mtex[a], sizeof(MTex));
235                         id_us_plus((ID *)man->mtex[a]->tex);
236                 }
237         }
238         
239         if (ma->ramp_col) man->ramp_col = MEM_dupallocN(ma->ramp_col);
240         if (ma->ramp_spec) man->ramp_spec = MEM_dupallocN(ma->ramp_spec);
241         
242         if (ma->preview) man->preview = BKE_previewimg_copy(ma->preview);
243
244         if (ma->nodetree) {
245                 man->nodetree = ntreeCopyTree(ma->nodetree);
246         }
247
248         man->gpumaterial.first = man->gpumaterial.last = NULL;
249         
250         return man;
251 }
252
253 /* XXX (see above) material copy without adding to main dbase */
254 Material *localize_material(Material *ma)
255 {
256         Material *man;
257         int a;
258         
259         man = BKE_libblock_copy(&ma->id);
260         BLI_remlink(&G.main->mat, man);
261
262         /* no increment for texture ID users, in previewrender.c it prevents decrement */
263         for (a = 0; a < MAX_MTEX; a++) {
264                 if (ma->mtex[a]) {
265                         man->mtex[a] = MEM_mallocN(sizeof(MTex), "copymaterial");
266                         memcpy(man->mtex[a], ma->mtex[a], sizeof(MTex));
267                 }
268         }
269         
270         if (ma->ramp_col) man->ramp_col = MEM_dupallocN(ma->ramp_col);
271         if (ma->ramp_spec) man->ramp_spec = MEM_dupallocN(ma->ramp_spec);
272         
273         man->preview = NULL;
274         
275         if (ma->nodetree)
276                 man->nodetree = ntreeLocalize(ma->nodetree);
277         
278         man->gpumaterial.first = man->gpumaterial.last = NULL;
279         
280         return man;
281 }
282
283 static void extern_local_material(Material *ma)
284 {
285         int i;
286         for (i = 0; i < MAX_MTEX; i++) {
287                 if (ma->mtex[i]) id_lib_extern((ID *)ma->mtex[i]->tex);
288         }
289 }
290
291 void BKE_material_make_local(Material *ma)
292 {
293         Main *bmain = G.main;
294         Object *ob;
295         Mesh *me;
296         Curve *cu;
297         MetaBall *mb;
298         int a, is_local = FALSE, is_lib = FALSE;
299
300         /* - only lib users: do nothing
301          * - only local users: set flag
302          * - mixed: make copy
303          */
304         
305         if (ma->id.lib == NULL) return;
306
307         /* One local user; set flag and return. */
308         if (ma->id.us == 1) {
309                 id_clear_lib_data(bmain, &ma->id);
310                 extern_local_material(ma);
311                 return;
312         }
313
314         /* Check which other IDs reference this one to determine if it's used by
315          * lib or local */
316         /* test objects */
317         ob = bmain->object.first;
318         while (ob) {
319                 if (ob->mat) {
320                         for (a = 0; a < ob->totcol; a++) {
321                                 if (ob->mat[a] == ma) {
322                                         if (ob->id.lib) is_lib = TRUE;
323                                         else is_local = TRUE;
324                                 }
325                         }
326                 }
327                 ob = ob->id.next;
328         }
329         /* test meshes */
330         me = bmain->mesh.first;
331         while (me) {
332                 if (me->mat) {
333                         for (a = 0; a < me->totcol; a++) {
334                                 if (me->mat[a] == ma) {
335                                         if (me->id.lib) is_lib = TRUE;
336                                         else is_local = TRUE;
337                                 }
338                         }
339                 }
340                 me = me->id.next;
341         }
342         /* test curves */
343         cu = bmain->curve.first;
344         while (cu) {
345                 if (cu->mat) {
346                         for (a = 0; a < cu->totcol; a++) {
347                                 if (cu->mat[a] == ma) {
348                                         if (cu->id.lib) is_lib = TRUE;
349                                         else is_local = TRUE;
350                                 }
351                         }
352                 }
353                 cu = cu->id.next;
354         }
355         /* test mballs */
356         mb = bmain->mball.first;
357         while (mb) {
358                 if (mb->mat) {
359                         for (a = 0; a < mb->totcol; a++) {
360                                 if (mb->mat[a] == ma) {
361                                         if (mb->id.lib) is_lib = TRUE;
362                                         else is_local = TRUE;
363                                 }
364                         }
365                 }
366                 mb = mb->id.next;
367         }
368
369         /* Only local users. */
370         if (is_local && is_lib == FALSE) {
371                 id_clear_lib_data(bmain, &ma->id);
372                 extern_local_material(ma);
373         }
374         /* Both user and local, so copy. */
375         else if (is_local && is_lib) {
376                 Material *ma_new = BKE_material_copy(ma);
377
378                 ma_new->id.us = 0;
379
380                 /* Remap paths of new ID using old library as base. */
381                 BKE_id_lib_local_paths(bmain, ma->id.lib, &ma_new->id);
382
383                 /* do objects */
384                 ob = bmain->object.first;
385                 while (ob) {
386                         if (ob->mat) {
387                                 for (a = 0; a < ob->totcol; a++) {
388                                         if (ob->mat[a] == ma) {
389                                                 if (ob->id.lib == NULL) {
390                                                         ob->mat[a] = ma_new;
391                                                         ma_new->id.us++;
392                                                         ma->id.us--;
393                                                 }
394                                         }
395                                 }
396                         }
397                         ob = ob->id.next;
398                 }
399                 /* do meshes */
400                 me = bmain->mesh.first;
401                 while (me) {
402                         if (me->mat) {
403                                 for (a = 0; a < me->totcol; a++) {
404                                         if (me->mat[a] == ma) {
405                                                 if (me->id.lib == NULL) {
406                                                         me->mat[a] = ma_new;
407                                                         ma_new->id.us++;
408                                                         ma->id.us--;
409                                                 }
410                                         }
411                                 }
412                         }
413                         me = me->id.next;
414                 }
415                 /* do curves */
416                 cu = bmain->curve.first;
417                 while (cu) {
418                         if (cu->mat) {
419                                 for (a = 0; a < cu->totcol; a++) {
420                                         if (cu->mat[a] == ma) {
421                                                 if (cu->id.lib == NULL) {
422                                                         cu->mat[a] = ma_new;
423                                                         ma_new->id.us++;
424                                                         ma->id.us--;
425                                                 }
426                                         }
427                                 }
428                         }
429                         cu = cu->id.next;
430                 }
431                 /* do mballs */
432                 mb = bmain->mball.first;
433                 while (mb) {
434                         if (mb->mat) {
435                                 for (a = 0; a < mb->totcol; a++) {
436                                         if (mb->mat[a] == ma) {
437                                                 if (mb->id.lib == NULL) {
438                                                         mb->mat[a] = ma_new;
439                                                         ma_new->id.us++;
440                                                         ma->id.us--;
441                                                 }
442                                         }
443                                 }
444                         }
445                         mb = mb->id.next;
446                 }
447         }
448 }
449
450 /* for curve, mball, mesh types */
451 void extern_local_matarar(struct Material **matar, short totcol)
452 {
453         short i;
454         for (i = 0; i < totcol; i++) {
455                 id_lib_extern((ID *)matar[i]);
456         }
457 }
458
459 Material ***give_matarar(Object *ob)
460 {
461         Mesh *me;
462         Curve *cu;
463         MetaBall *mb;
464         
465         if (ob->type == OB_MESH) {
466                 me = ob->data;
467                 return &(me->mat);
468         }
469         else if (ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
470                 cu = ob->data;
471                 return &(cu->mat);
472         }
473         else if (ob->type == OB_MBALL) {
474                 mb = ob->data;
475                 return &(mb->mat);
476         }
477         return NULL;
478 }
479
480 short *give_totcolp(Object *ob)
481 {
482         Mesh *me;
483         Curve *cu;
484         MetaBall *mb;
485         
486         if (ob->type == OB_MESH) {
487                 me = ob->data;
488                 return &(me->totcol);
489         }
490         else if (ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
491                 cu = ob->data;
492                 return &(cu->totcol);
493         }
494         else if (ob->type == OB_MBALL) {
495                 mb = ob->data;
496                 return &(mb->totcol);
497         }
498         return NULL;
499 }
500
501 /* same as above but for ID's */
502 Material ***give_matarar_id(ID *id)
503 {
504         /* ensure we don't try get materials from non-obdata */
505         BLI_assert(OB_DATA_SUPPORT_ID(GS(id->name)));
506
507         switch (GS(id->name)) {
508                 case ID_ME:
509                         return &(((Mesh *)id)->mat);
510                         break;
511                 case ID_CU:
512                         return &(((Curve *)id)->mat);
513                         break;
514                 case ID_MB:
515                         return &(((MetaBall *)id)->mat);
516                         break;
517         }
518         return NULL;
519 }
520
521 short *give_totcolp_id(ID *id)
522 {
523         /* ensure we don't try get materials from non-obdata */
524         BLI_assert(OB_DATA_SUPPORT_ID(GS(id->name)));
525
526         switch (GS(id->name)) {
527                 case ID_ME:
528                         return &(((Mesh *)id)->totcol);
529                         break;
530                 case ID_CU:
531                         return &(((Curve *)id)->totcol);
532                         break;
533                 case ID_MB:
534                         return &(((MetaBall *)id)->totcol);
535                         break;
536         }
537         return NULL;
538 }
539
540 static void data_delete_material_index_id(ID *id, short index)
541 {
542         /* ensure we don't try get materials from non-obdata */
543         BLI_assert(OB_DATA_SUPPORT_ID(GS(id->name)));
544
545         switch (GS(id->name)) {
546                 case ID_ME:
547                         BKE_mesh_delete_material_index((Mesh *)id, index);
548                         break;
549                 case ID_CU:
550                         BKE_curve_delete_material_index((Curve *)id, index);
551                         break;
552                 case ID_MB:
553                         /* meta-elems don't have materials atm */
554                         break;
555         }
556 }
557
558 void material_append_id(ID *id, Material *ma)
559 {
560         Material ***matar;
561         if ((matar = give_matarar_id(id))) {
562                 short *totcol = give_totcolp_id(id);
563                 Material **mat = MEM_callocN(sizeof(void *) * ((*totcol) + 1), "newmatar");
564                 if (*totcol) memcpy(mat, *matar, sizeof(void *) * (*totcol));
565                 if (*matar) MEM_freeN(*matar);
566
567                 *matar = mat;
568                 (*matar)[(*totcol)++] = ma;
569
570                 id_us_plus((ID *)ma);
571                 test_object_materials(G.main, id);
572         }
573 }
574
575 Material *material_pop_id(ID *id, int index_i, int remove_material_slot)
576 {
577         short index = (short)index_i;
578         Material *ret = NULL;
579         Material ***matar;
580         if ((matar = give_matarar_id(id))) {
581                 short *totcol = give_totcolp_id(id);
582                 if (index >= 0 && index < (*totcol)) {
583                         ret = (*matar)[index];
584                         id_us_min((ID *)ret);
585
586                         if (remove_material_slot) {
587                                 if (*totcol <= 1) {
588                                         *totcol = 0;
589                                         MEM_freeN(*matar);
590                                         *matar = NULL;
591                                 }
592                                 else {
593                                         Material **mat;
594                                         if (index + 1 != (*totcol))
595                                                 memmove((*matar) + index, (*matar) + (index + 1), sizeof(void *) * ((*totcol) - (index + 1)));
596
597                                         (*totcol)--;
598                                         
599                                         mat = MEM_callocN(sizeof(void *) * (*totcol), "newmatar");
600                                         memcpy(mat, *matar, sizeof(void *) * (*totcol));
601                                         MEM_freeN(*matar);
602
603                                         *matar = mat;
604                                         test_object_materials(G.main, id);
605                                 }
606
607                                 /* decrease mat_nr index */
608                                 data_delete_material_index_id(id, index);
609                         }
610
611                         /* don't remove material slot, only clear it*/
612                         else
613                                 (*matar)[index] = NULL;
614                 }
615         }
616         
617         return ret;
618 }
619
620 Material *give_current_material(Object *ob, short act)
621 {
622         Material ***matarar, *ma;
623         short *totcolp;
624         
625         if (ob == NULL) return NULL;
626         
627         /* if object cannot have material, (totcolp == NULL) */
628         totcolp = give_totcolp(ob);
629         if (totcolp == NULL || ob->totcol == 0) return NULL;
630         
631         if (act < 0) {
632                 printf("Negative material index!\n");
633         }
634         
635         /* return NULL for invalid 'act', can happen for mesh face indices */
636         if (act > ob->totcol)
637                 return NULL;
638         else if (act <= 0)
639                 return NULL;
640
641         if (ob->matbits && ob->matbits[act - 1]) {    /* in object */
642                 ma = ob->mat[act - 1];
643         }
644         else {                              /* in data */
645
646                 /* check for inconsistency */
647                 if (*totcolp < ob->totcol)
648                         ob->totcol = *totcolp;
649                 if (act > ob->totcol) act = ob->totcol;
650
651                 matarar = give_matarar(ob);
652                 
653                 if (matarar && *matarar) ma = (*matarar)[act - 1];
654                 else ma = NULL;
655                 
656         }
657         
658         return ma;
659 }
660
661 ID *material_from(Object *ob, short act)
662 {
663
664         if (ob == NULL) return NULL;
665
666         if (ob->totcol == 0) return ob->data;
667         if (act == 0) act = 1;
668
669         if (ob->matbits[act - 1]) return (ID *)ob;
670         else return ob->data;
671 }
672
673 Material *give_node_material(Material *ma)
674 {
675         if (ma && ma->use_nodes && ma->nodetree) {
676                 bNode *node = nodeGetActiveID(ma->nodetree, ID_MA);
677
678                 if (node)
679                         return (Material *)node->id;
680         }
681
682         return NULL;
683 }
684
685 void resize_object_material(Object *ob, const short totcol)
686 {
687         Material **newmatar;
688         char *newmatbits;
689
690         if (totcol == 0) {
691                 if (ob->totcol) {
692                         MEM_freeN(ob->mat);
693                         MEM_freeN(ob->matbits);
694                         ob->mat = NULL;
695                         ob->matbits = NULL;
696                 }
697         }
698         else if (ob->totcol < totcol) {
699                 newmatar = MEM_callocN(sizeof(void *) * totcol, "newmatar");
700                 newmatbits = MEM_callocN(sizeof(char) * totcol, "newmatbits");
701                 if (ob->totcol) {
702                         memcpy(newmatar, ob->mat, sizeof(void *) * ob->totcol);
703                         memcpy(newmatbits, ob->matbits, sizeof(char) * ob->totcol);
704                         MEM_freeN(ob->mat);
705                         MEM_freeN(ob->matbits);
706                 }
707                 ob->mat = newmatar;
708                 ob->matbits = newmatbits;
709         }
710         ob->totcol = totcol;
711         if (ob->totcol && ob->actcol == 0) ob->actcol = 1;
712         if (ob->actcol > ob->totcol) ob->actcol = ob->totcol;
713 }
714
715 void test_object_materials(Main *bmain, ID *id)
716 {
717         /* make the ob mat-array same size as 'ob->data' mat-array */
718         Object *ob;
719         short *totcol;
720
721         if (id == NULL || (totcol = give_totcolp_id(id)) == NULL) {
722                 return;
723         }
724
725         for (ob = bmain->object.first; ob; ob = ob->id.next) {
726                 if (ob->data == id) {
727                         resize_object_material(ob, *totcol);
728                 }
729         }
730 }
731
732 void assign_material_id(ID *id, Material *ma, short act)
733 {
734         Material *mao, **matar, ***matarar;
735         short *totcolp;
736
737         if (act > MAXMAT) return;
738         if (act < 1) act = 1;
739
740         /* prevent crashing when using accidentally */
741         BLI_assert(id->lib == NULL);
742         if (id->lib) return;
743
744         /* test arraylens */
745
746         totcolp = give_totcolp_id(id);
747         matarar = give_matarar_id(id);
748
749         if (totcolp == NULL || matarar == NULL) return;
750
751         if (act > *totcolp) {
752                 matar = MEM_callocN(sizeof(void *) * act, "matarray1");
753
754                 if (*totcolp) {
755                         memcpy(matar, *matarar, sizeof(void *) * (*totcolp));
756                         MEM_freeN(*matarar);
757                 }
758
759                 *matarar = matar;
760                 *totcolp = act;
761         }
762
763         /* in data */
764         mao = (*matarar)[act - 1];
765         if (mao) mao->id.us--;
766         (*matarar)[act - 1] = ma;
767
768         if (ma)
769                 id_us_plus((ID *)ma);
770
771         test_object_materials(G.main, id);
772 }
773
774 void assign_material(Object *ob, Material *ma, short act, int assign_type)
775 {
776         Material *mao, **matar, ***matarar;
777         char *matbits;
778         short *totcolp;
779         char bit = 0;
780
781         if (act > MAXMAT) return;
782         if (act < 1) act = 1;
783         
784         /* prevent crashing when using accidentally */
785         BLI_assert(ob->id.lib == NULL);
786         if (ob->id.lib) return;
787         
788         /* test arraylens */
789         
790         totcolp = give_totcolp(ob);
791         matarar = give_matarar(ob);
792         
793         if (totcolp == NULL || matarar == NULL) return;
794         
795         if (act > *totcolp) {
796                 matar = MEM_callocN(sizeof(void *) * act, "matarray1");
797
798                 if (*totcolp) {
799                         memcpy(matar, *matarar, sizeof(void *) * (*totcolp));
800                         MEM_freeN(*matarar);
801                 }
802
803                 *matarar = matar;
804                 *totcolp = act;
805         }
806
807         /* Determine the object/mesh linking */
808         if (assign_type == BKE_MAT_ASSIGN_USERPREF && ob->totcol && ob->actcol) {
809                 /* copy from previous material */
810                 bit = ob->matbits[ob->actcol - 1];
811         }
812         else {
813                 switch (assign_type) {
814                         case BKE_MAT_ASSIGN_OBDATA:
815                                 bit = 0;
816                                 break;
817                         case BKE_MAT_ASSIGN_OBJECT:
818                                 bit = 1;
819                                 break;
820                         case BKE_MAT_ASSIGN_USERPREF:
821                         default:
822                                 bit = (U.flag & USER_MAT_ON_OB) ? 1 : 0;
823                                 break;
824                 }
825         }
826
827         if (act > ob->totcol) {
828                 /* Need more space in the material arrays */
829                 matar = MEM_callocN(sizeof(void *) * act, "matarray2");
830                 matbits = MEM_callocN(sizeof(char) * act, "matbits1");
831                 if (ob->totcol) {
832                         memcpy(matar, ob->mat, sizeof(void *) * ob->totcol);
833                         memcpy(matbits, ob->matbits, sizeof(char) * (*totcolp));
834                         MEM_freeN(ob->mat);
835                         MEM_freeN(ob->matbits);
836                 }
837                 ob->mat = matar;
838                 ob->matbits = matbits;
839                 ob->totcol = act;
840         }
841         
842         /* do it */
843
844         ob->matbits[act - 1] = bit;
845         if (bit == 1) {   /* in object */
846                 mao = ob->mat[act - 1];
847                 if (mao) mao->id.us--;
848                 ob->mat[act - 1] = ma;
849         }
850         else {  /* in data */
851                 mao = (*matarar)[act - 1];
852                 if (mao) mao->id.us--;
853                 (*matarar)[act - 1] = ma;
854         }
855
856         if (ma)
857                 id_us_plus((ID *)ma);
858         test_object_materials(G.main, ob->data);
859 }
860
861 /* XXX - this calls many more update calls per object then are needed, could be optimized */
862 void assign_matarar(struct Object *ob, struct Material ***matar, short totcol)
863 {
864         int actcol_orig = ob->actcol;
865         short i;
866
867         while (object_remove_material_slot(ob)) {}
868
869         /* now we have the right number of slots */
870         for (i = 0; i < totcol; i++)
871                 assign_material(ob, (*matar)[i], i + 1, BKE_MAT_ASSIGN_USERPREF);
872
873         if (actcol_orig > ob->totcol)
874                 actcol_orig = ob->totcol;
875
876         ob->actcol = actcol_orig;
877 }
878
879
880 short find_material_index(Object *ob, Material *ma)
881 {
882         Material ***matarar;
883         short a, *totcolp;
884         
885         if (ma == NULL) return 0;
886         
887         totcolp = give_totcolp(ob);
888         matarar = give_matarar(ob);
889         
890         if (totcolp == NULL || matarar == NULL) return 0;
891         
892         for (a = 0; a < *totcolp; a++)
893                 if ((*matarar)[a] == ma)
894                         break;
895         if (a < *totcolp)
896                 return a + 1;
897         return 0;
898 }
899
900 int object_add_material_slot(Object *ob)
901 {
902         if (ob == NULL) return FALSE;
903         if (ob->totcol >= MAXMAT) return FALSE;
904         
905         assign_material(ob, NULL, ob->totcol + 1, BKE_MAT_ASSIGN_USERPREF);
906         ob->actcol = ob->totcol;
907         return TRUE;
908 }
909
910 static void do_init_render_material(Material *ma, int r_mode, float *amb)
911 {
912         MTex *mtex;
913         int a, needuv = 0, needtang = 0;
914         
915         if (ma->flarec == 0) ma->flarec = 1;
916
917         /* add all texcoflags from mtex, texco and mapto were cleared in advance */
918         for (a = 0; a < MAX_MTEX; a++) {
919                 
920                 /* separate tex switching */
921                 if (ma->septex & (1 << a)) continue;
922
923                 mtex = ma->mtex[a];
924                 if (mtex && mtex->tex && (mtex->tex->type | (mtex->tex->use_nodes && mtex->tex->nodetree) )) {
925                         
926                         ma->texco |= mtex->texco;
927                         ma->mapto |= mtex->mapto;
928
929                         /* always get derivatives for these textures */
930                         if (ELEM(mtex->tex->type, TEX_IMAGE, TEX_ENVMAP)) ma->texco |= TEXCO_OSA;
931                         else if (mtex->texflag & (MTEX_COMPAT_BUMP | MTEX_3TAP_BUMP | MTEX_5TAP_BUMP | MTEX_BICUBIC_BUMP)) ma->texco |= TEXCO_OSA;
932                         
933                         if (ma->texco & (TEXCO_ORCO | TEXCO_REFL | TEXCO_NORM | TEXCO_STRAND | TEXCO_STRESS)) needuv = 1;
934                         else if (ma->texco & (TEXCO_GLOB | TEXCO_UV | TEXCO_OBJECT | TEXCO_SPEED)) needuv = 1;
935                         else if (ma->texco & (TEXCO_LAVECTOR | TEXCO_VIEW)) needuv = 1;
936
937                         if ((ma->mapto & MAP_NORM) && (mtex->normapspace == MTEX_NSPACE_TANGENT))
938                                 needtang = 1;
939                 }
940         }
941
942         if (needtang) ma->mode |= MA_NORMAP_TANG;
943         else ma->mode &= ~MA_NORMAP_TANG;
944         
945         if (ma->mode & (MA_VERTEXCOL | MA_VERTEXCOLP | MA_FACETEXTURE)) {
946                 needuv = 1;
947                 if (r_mode & R_OSA) ma->texco |= TEXCO_OSA;     /* for texfaces */
948         }
949         if (needuv) ma->texco |= NEED_UV;
950         
951         /* since the raytracer doesnt recalc O structs for each ray, we have to preset them all */
952         if (r_mode & R_RAYTRACE) {
953                 if ((ma->mode & (MA_RAYMIRROR | MA_SHADOW_TRA)) || ((ma->mode & MA_TRANSP) && (ma->mode & MA_RAYTRANSP))) {
954                         ma->texco |= NEED_UV | TEXCO_ORCO | TEXCO_REFL | TEXCO_NORM;
955                         if (r_mode & R_OSA) ma->texco |= TEXCO_OSA;
956                 }
957         }
958         
959         if (amb) {
960                 ma->ambr = ma->amb * amb[0];
961                 ma->ambg = ma->amb * amb[1];
962                 ma->ambb = ma->amb * amb[2];
963         }
964         /* will become or-ed result of all node modes */
965         ma->mode_l = ma->mode;
966         ma->mode_l &= ~MA_SHLESS;
967
968         if (ma->strand_surfnor > 0.0f)
969                 ma->mode_l |= MA_STR_SURFDIFF;
970
971         /* parses the geom+tex nodes */
972         if (ma->nodetree && ma->use_nodes)
973                 ntreeShaderGetTexcoMode(ma->nodetree, r_mode, &ma->texco, &ma->mode_l);
974
975         /* local group override */
976         if ((ma->shade_flag & MA_GROUP_LOCAL) && ma->id.lib && ma->group && ma->group->id.lib) {
977                 Group *group;
978
979                 for (group = G.main->group.first; group; group = group->id.next) {
980                         if (!group->id.lib && strcmp(group->id.name, ma->group->id.name) == 0) {
981                                 ma->group = group;
982                         }
983                 }
984         }
985 }
986
987 static void init_render_nodetree(bNodeTree *ntree, Material *basemat, int r_mode, float *amb)
988 {
989         bNode *node;
990         
991         for (node = ntree->nodes.first; node; node = node->next) {
992                 if (node->id) {
993                         if (GS(node->id->name) == ID_MA) {
994                                 Material *ma = (Material *)node->id;
995                                 if (ma != basemat) {
996                                         do_init_render_material(ma, r_mode, amb);
997                                         basemat->texco |= ma->texco;
998                                         basemat->mode_l |= ma->mode_l & ~(MA_TRANSP | MA_ZTRANSP | MA_RAYTRANSP);
999                                 }
1000                         }
1001                         else if (node->type == NODE_GROUP)
1002                                 init_render_nodetree((bNodeTree *)node->id, basemat, r_mode, amb);
1003                 }
1004         }
1005 }
1006
1007 void init_render_material(Material *mat, int r_mode, float *amb)
1008 {
1009         
1010         do_init_render_material(mat, r_mode, amb);
1011         
1012         if (mat->nodetree && mat->use_nodes) {
1013                 init_render_nodetree(mat->nodetree, mat, r_mode, amb);
1014                 
1015                 if (!mat->nodetree->execdata)
1016                         mat->nodetree->execdata = ntreeShaderBeginExecTree(mat->nodetree);
1017         }
1018 }
1019
1020 void init_render_materials(Main *bmain, int r_mode, float *amb)
1021 {
1022         Material *ma;
1023         
1024         /* clear these flags before going over materials, to make sure they
1025          * are cleared only once, otherwise node materials contained in other
1026          * node materials can go wrong */
1027         for (ma = bmain->mat.first; ma; ma = ma->id.next) {
1028                 if (ma->id.us) {
1029                         ma->texco = 0;
1030                         ma->mapto = 0;
1031                 }
1032         }
1033
1034         /* two steps, first initialize, then or the flags for layers */
1035         for (ma = bmain->mat.first; ma; ma = ma->id.next) {
1036                 /* is_used flag comes back in convertblender.c */
1037                 ma->flag &= ~MA_IS_USED;
1038                 if (ma->id.us) 
1039                         init_render_material(ma, r_mode, amb);
1040         }
1041         
1042         do_init_render_material(&defmaterial, r_mode, amb);
1043 }
1044
1045 /* only needed for nodes now */
1046 void end_render_material(Material *mat)
1047 {
1048         if (mat && mat->nodetree && mat->use_nodes) {
1049                 if (mat->nodetree->execdata)
1050                         ntreeShaderEndExecTree(mat->nodetree->execdata);
1051         }
1052 }
1053
1054 void end_render_materials(Main *bmain)
1055 {
1056         Material *ma;
1057         for (ma = bmain->mat.first; ma; ma = ma->id.next)
1058                 if (ma->id.us) 
1059                         end_render_material(ma);
1060 }
1061
1062 static int material_in_nodetree(bNodeTree *ntree, Material *mat)
1063 {
1064         bNode *node;
1065
1066         for (node = ntree->nodes.first; node; node = node->next) {
1067                 if (node->id) {
1068                         if (GS(node->id->name) == ID_MA) {
1069                                 if (node->id == (ID *)mat) {
1070                                         return 1;
1071                                 }
1072                         }
1073                         else if (node->type == NODE_GROUP) {
1074                                 if (material_in_nodetree((bNodeTree *)node->id, mat)) {
1075                                         return 1;
1076                                 }
1077                         }
1078                 }
1079         }
1080
1081         return 0;
1082 }
1083
1084 int material_in_material(Material *parmat, Material *mat)
1085 {
1086         if (parmat == mat)
1087                 return 1;
1088         else if (parmat->nodetree && parmat->use_nodes)
1089                 return material_in_nodetree(parmat->nodetree, mat);
1090         else
1091                 return 0;
1092 }
1093
1094
1095 /* ****************** */
1096
1097 /* Update drivers for materials in a nodetree */
1098 static void material_node_drivers_update(Scene *scene, bNodeTree *ntree, float ctime)
1099 {
1100         bNode *node;
1101
1102         /* nodetree itself */
1103         if (ntree->adt && ntree->adt->drivers.first) {
1104                 BKE_animsys_evaluate_animdata(scene, &ntree->id, ntree->adt, ctime, ADT_RECALC_DRIVERS);
1105         }
1106         
1107         /* nodes */
1108         for (node = ntree->nodes.first; node; node = node->next) {
1109                 if (node->id) {
1110                         if (GS(node->id->name) == ID_MA) {
1111                                 material_drivers_update(scene, (Material *)node->id, ctime);
1112                         }
1113                         else if (node->type == NODE_GROUP) {
1114                                 material_node_drivers_update(scene, (bNodeTree *)node->id, ctime);
1115                         }
1116                 }
1117         }
1118 }
1119
1120 /* Calculate all drivers for materials 
1121  * FIXME: this is really a terrible method which may result in some things being calculated
1122  * multiple times. However, without proper despgraph support for these things, we are forced
1123  * into this sort of thing...
1124  */
1125 void material_drivers_update(Scene *scene, Material *ma, float ctime)
1126 {
1127         //if (G.f & G_DEBUG)
1128         //      printf("material_drivers_update(%s, %s)\n", scene->id.name, ma->id.name);
1129         
1130         /* Prevent infinite recursion by checking (and tagging the material) as having been visited already
1131          * (see BKE_scene_update_tagged()). This assumes ma->id.flag & LIB_DOIT isn't set by anything else
1132          * in the meantime... [#32017]
1133          */
1134         if (ma->id.flag & LIB_DOIT)
1135                 return;
1136
1137         ma->id.flag |= LIB_DOIT;
1138         
1139         /* material itself */
1140         if (ma->adt && ma->adt->drivers.first) {
1141                 BKE_animsys_evaluate_animdata(scene, &ma->id, ma->adt, ctime, ADT_RECALC_DRIVERS);
1142         }
1143         
1144         /* nodes */
1145         if (ma->nodetree) {
1146                 material_node_drivers_update(scene, ma->nodetree, ctime);
1147         }
1148
1149         ma->id.flag &= ~LIB_DOIT;
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                         break;
1434                 }
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                         break;
1445                 }
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                         break;
1454                 }
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                         break;
1469                 }
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                         break;
1483                 }
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) {
1601                                 /* first check this is in main (we may have loaded another file) [#35500] */
1602                                 if (BLI_findindex(&G.main->tex, mtex->tex) != -1) {
1603                                         id_us_plus((ID *)mtex->tex);
1604                                 }
1605                                 else {
1606                                         ma->mtex[a]->tex = NULL;
1607                                 }
1608                         }
1609                 }
1610         }
1611
1612         ma->nodetree = ntreeCopyTree_ex(matcopybuf.nodetree, FALSE);
1613 }
1614
1615
1616 /*********************** texface to material convert functions **********************/
1617 /* encode all the TF information into a single int */
1618 static int encode_tfaceflag(MTFace *tf, int convertall)
1619 {
1620         /* calculate the flag */
1621         int flag = tf->mode;
1622
1623         /* options that change the material offline render */
1624         if (!convertall) {
1625                 flag &= ~TF_OBCOL;
1626         }
1627
1628         /* clean flags that are not being converted */
1629         flag &= ~TF_TEX;
1630         flag &= ~TF_SHAREDVERT;
1631         flag &= ~TF_SHAREDCOL;
1632         flag &= ~TF_CONVERTED;
1633
1634         /* light tface flag is ignored in GLSL mode */
1635         flag &= ~TF_LIGHT;
1636         
1637         /* 15 is how big the flag can be - hardcoded here and in decode_tfaceflag() */
1638         flag |= tf->transp << 15;
1639         
1640         /* increase 1 so flag 0 is different than no flag yet */
1641         return flag + 1;
1642 }
1643
1644 /* set the material options based in the tface flag */
1645 static void decode_tfaceflag(Material *ma, int flag, int convertall)
1646 {
1647         int alphablend;
1648         GameSettings *game = &ma->game;
1649
1650         /* flag is shifted in 1 to make 0 != no flag yet (see encode_tfaceflag) */
1651         flag -= 1;
1652
1653         alphablend = flag >> 15;  /* encoded in the encode_tfaceflag function */
1654         (*game).flag = 0;
1655         
1656         /* General Material Options */
1657         if ((flag & TF_DYNAMIC) == 0) (*game).flag    |= GEMAT_NOPHYSICS;
1658         
1659         /* Material Offline Rendering Properties */
1660         if (convertall) {
1661                 if (flag & TF_OBCOL) ma->shade_flag |= MA_OBCOLOR;
1662         }
1663         
1664         /* Special Face Properties */
1665         if ((flag & TF_TWOSIDE) == 0) (*game).flag |= GEMAT_BACKCULL;
1666         if (flag & TF_INVISIBLE) (*game).flag |= GEMAT_INVISIBLE;
1667         if (flag & TF_BMFONT) (*game).flag |= GEMAT_TEXT;
1668         
1669         /* Face Orientation */
1670         if (flag & TF_BILLBOARD) (*game).face_orientation |= GEMAT_HALO;
1671         else if (flag & TF_BILLBOARD2) (*game).face_orientation |= GEMAT_BILLBOARD;
1672         else if (flag & TF_SHADOW) (*game).face_orientation |= GEMAT_SHADOW;
1673         
1674         /* Alpha Blend */
1675         if (flag & TF_ALPHASORT && ELEM(alphablend, TF_ALPHA, TF_ADD)) (*game).alpha_blend = GEMAT_ALPHA_SORT;
1676         else if (alphablend & TF_ALPHA) (*game).alpha_blend = GEMAT_ALPHA;
1677         else if (alphablend & TF_ADD) (*game).alpha_blend = GEMAT_ADD;
1678         else if (alphablend & TF_CLIP) (*game).alpha_blend = GEMAT_CLIP;
1679 }
1680
1681 /* boolean check to see if the mesh needs a material */
1682 static int check_tfaceneedmaterial(int flag)
1683 {
1684         /* check if the flags we have are not deprecated != than default material options
1685          * also if only flags are visible and collision see if all objects using this mesh have this option in physics */
1686
1687         /* flag is shifted in 1 to make 0 != no flag yet (see encode_tfaceflag) */
1688         flag -= 1;
1689
1690         /* deprecated flags */
1691         flag &= ~TF_OBCOL;
1692         flag &= ~TF_SHAREDVERT;
1693         flag &= ~TF_SHAREDCOL;
1694
1695         /* light tface flag is ignored in GLSL mode */
1696         flag &= ~TF_LIGHT;
1697         
1698         /* automatic detected if tex image has alpha */
1699         flag &= ~(TF_ALPHA << 15);
1700         /* automatic detected if using texture */
1701         flag &= ~TF_TEX;
1702
1703         /* settings for the default NoMaterial */
1704         if (flag == TF_DYNAMIC)
1705                 return 0;
1706
1707         else
1708                 return 1;
1709 }
1710
1711 /* return number of digits of an integer */
1712 /* XXX to be optmized or replaced by an equivalent blender internal function */
1713 static int integer_getdigits(int number)
1714 {
1715         int i = 0;
1716         if (number == 0) return 1;
1717
1718         while (number != 0) {
1719                 number = (int)(number / 10);
1720                 i++;
1721         }
1722         return i;
1723 }
1724
1725 static void calculate_tface_materialname(char *matname, char *newname, int flag)
1726 {
1727         /* if flag has only light and collision and material matches those values
1728          * you can do strcpy(name, mat_name);
1729          * otherwise do: */
1730         int digits = integer_getdigits(flag);
1731         /* clamp the old name, remove the MA prefix and add the .TF.flag suffix
1732          * e.g. matname = "MALoooooooooooooongName"; newname = "Loooooooooooooon.TF.2" */
1733         BLI_snprintf(newname, MAX_ID_NAME, "%.*s.TF.%0*d", MAX_ID_NAME - (digits + 5), matname, digits, flag);
1734 }
1735
1736 /* returns -1 if no match */
1737 static short mesh_getmaterialnumber(Mesh *me, Material *ma)
1738 {
1739         short a;
1740
1741         for (a = 0; a < me->totcol; a++) {
1742                 if (me->mat[a] == ma) {
1743                         return a;
1744                 }
1745         }
1746
1747         return -1;
1748 }
1749
1750 /* append material */
1751 static short mesh_addmaterial(Mesh *me, Material *ma)
1752 {
1753         material_append_id(&me->id, NULL);
1754         me->mat[me->totcol - 1] = ma;
1755
1756         id_us_plus(&ma->id);
1757
1758         return me->totcol - 1;
1759 }
1760
1761 static void set_facetexture_flags(Material *ma, Image *image)
1762 {
1763         if (image) {
1764                 ma->mode |= MA_FACETEXTURE;
1765                 /* we could check if the texture has alpha, but then more meshes sharing the same
1766                  * material may need it. Let's make it simple. */
1767                 if (BKE_image_has_alpha(image))
1768                         ma->mode |= MA_FACETEXTURE_ALPHA;
1769         }
1770 }
1771
1772 /* returns material number */
1773 static short convert_tfacenomaterial(Main *main, Mesh *me, MTFace *tf, int flag)
1774 {
1775         Material *ma;
1776         char idname[MAX_ID_NAME];
1777         short mat_nr = -1;
1778         
1779         /* new material, the name uses the flag*/
1780         BLI_snprintf(idname, sizeof(idname), "MAMaterial.TF.%0*d", integer_getdigits(flag), flag);
1781
1782         if ((ma = BLI_findstring(&main->mat, idname + 2, offsetof(ID, name) + 2))) {
1783                 mat_nr = mesh_getmaterialnumber(me, ma);
1784                 /* assign the material to the mesh */
1785                 if (mat_nr == -1) mat_nr = mesh_addmaterial(me, ma);
1786
1787                 /* if needed set "Face Textures [Alpha]" Material options */
1788                 set_facetexture_flags(ma, tf->tpage);
1789         }
1790         /* create a new material */
1791         else {
1792                 ma = BKE_material_add(main, idname + 2);
1793
1794                 if (ma) {
1795                         printf("TexFace Convert: Material \"%s\" created.\n", idname + 2);
1796                         mat_nr = mesh_addmaterial(me, ma);
1797                         
1798                         /* if needed set "Face Textures [Alpha]" Material options */
1799                         set_facetexture_flags(ma, tf->tpage);
1800
1801                         decode_tfaceflag(ma, flag, 1);
1802                         /* the final decoding will happen after, outside the main loop
1803                          * for now store the flag into the material and change light/tex/collision
1804                          * store the flag as a negative number */
1805                         ma->game.flag = -flag;
1806                         id_us_min((ID *)ma);
1807                 }
1808                 else {
1809                         printf("Error: Unable to create Material \"%s\" for Mesh \"%s\".", idname + 2, me->id.name + 2);
1810                 }
1811         }
1812
1813         /* set as converted, no need to go bad to this face */
1814         tf->mode |= TF_CONVERTED;
1815         return mat_nr;
1816 }
1817
1818 /* Function to fully convert materials */
1819 static void convert_tfacematerial(Main *main, Material *ma)
1820 {
1821         Mesh *me;
1822         Material *mat_new;
1823         MFace *mf;
1824         MTFace *tf;
1825         int flag, index;
1826         int a;
1827         short mat_nr;
1828         CustomDataLayer *cdl;
1829         char idname[MAX_ID_NAME];
1830
1831         for (me = main->mesh.first; me; me = me->id.next) {
1832                 /* check if this mesh uses this material */
1833                 for (a = 0; a < me->totcol; a++)
1834                         if (me->mat[a] == ma) break;
1835                         
1836                 /* no material found */
1837                 if (a == me->totcol) continue;
1838
1839                 /* get the active tface layer */
1840                 index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
1841                 cdl = (index == -1) ? NULL : &me->fdata.layers[index];
1842                 if (!cdl) continue;
1843
1844                 /* loop over all the faces and stop at the ones that use the material*/
1845                 for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
1846                         if (me->mat[mf->mat_nr] != ma) continue;
1847
1848                         /* texface data for this face */
1849                         tf = ((MTFace *)cdl->data) + a;
1850                         flag = encode_tfaceflag(tf, 1);
1851
1852                         /* the name of the new material */
1853                         calculate_tface_materialname(ma->id.name, (char *)&idname, flag);
1854
1855                         if ((mat_new = BLI_findstring(&main->mat, idname + 2, offsetof(ID, name) + 2))) {
1856                                 /* material already existent, see if the mesh has it */
1857                                 mat_nr = mesh_getmaterialnumber(me, mat_new);
1858                                 /* material is not in the mesh, add it */
1859                                 if (mat_nr == -1) mat_nr = mesh_addmaterial(me, mat_new);
1860                         }
1861                         /* create a new material */
1862                         else {
1863                                 mat_new = BKE_material_copy(ma);
1864                                 if (mat_new) {
1865                                         /* rename the material*/
1866                                         BLI_strncpy(mat_new->id.name, idname, sizeof(mat_new->id.name));
1867                                         id_us_min((ID *)mat_new);
1868
1869                                         mat_nr = mesh_addmaterial(me, mat_new);
1870                                         decode_tfaceflag(mat_new, flag, 1);
1871                                 }
1872                                 else {
1873                                         printf("Error: Unable to create Material \"%s\" for Mesh \"%s.", idname + 2, me->id.name + 2);
1874                                         mat_nr = mf->mat_nr;
1875                                         continue;
1876                                 }
1877                         }
1878                         
1879                         /* if the material has a texture but no texture channel
1880                          * set "Face Textures [Alpha]" Material options 
1881                          * actually we need to run it always, because of old behavior
1882                          * of using face texture if any texture channel was present (multitex) */
1883                         //if ((!mat_new->mtex[0]) && (!mat_new->mtex[0]->tex))
1884                         set_facetexture_flags(mat_new, tf->tpage);
1885
1886                         /* set the material number to the face*/
1887                         mf->mat_nr = mat_nr;
1888                 }
1889                 /* remove material from mesh */
1890                 for (a = 0; a < me->totcol; )
1891                         if (me->mat[a] == ma) material_pop_id(&me->id, a, 1); else a++;
1892         }
1893 }
1894
1895
1896 #define MAT_BGE_DISPUTED -99999
1897
1898 int do_version_tface(Main *main, int fileload)
1899 {
1900         Mesh *me;
1901         Material *ma;
1902         MFace *mf;
1903         MTFace *tf;
1904         CustomDataLayer *cdl;
1905         int a;
1906         int flag;
1907         int index;
1908
1909         /* sometimes mesh has no materials but will need a new one. In those
1910          * cases we need to ignore the mf->mat_nr and only look at the face
1911          * mode because it can be zero as uninitialized or the 1st created material
1912          */
1913         int nomaterialslots;
1914
1915         /* alert to user to check the console */
1916         int nowarning = 1;
1917
1918         /* mark all the materials to conversion with a flag
1919          * if there is tface create a complete flag for that storing in flag
1920          * if there is tface and flag > 0: creates a new flag based on this face
1921          * if flags are different set flag to -1  
1922          */
1923         
1924         /* 1st part: marking mesh materials to update */
1925         for (me = main->mesh.first; me; me = me->id.next) {
1926                 if (me->id.lib) continue;
1927
1928                 /* get the active tface layer */
1929                 index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
1930                 cdl = (index == -1) ? NULL : &me->fdata.layers[index];
1931                 if (!cdl) continue;
1932
1933                 nomaterialslots = (me->totcol == 0 ? 1 : 0);
1934                 
1935                 /* loop over all the faces*/
1936                 for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
1937                         /* texface data for this face */
1938                         tf = ((MTFace *)cdl->data) + a;
1939
1940                         /* conversion should happen only once */
1941                         if (fileload)
1942                                 tf->mode &= ~TF_CONVERTED;
1943                         else {
1944                                 if ((tf->mode & TF_CONVERTED)) continue;
1945                                 else tf->mode |= TF_CONVERTED;
1946                         }
1947                         
1948                         /* no material slots */
1949                         if (nomaterialslots) {
1950                                 flag = encode_tfaceflag(tf, 1);
1951                                 
1952                                 /* create/find a new material and assign to the face */
1953                                 if (check_tfaceneedmaterial(flag)) {
1954                                         mf->mat_nr = convert_tfacenomaterial(main, me, tf, flag);
1955                                 }
1956                                 /* else mark them as no-material to be reverted to 0 later */
1957                                 else {
1958                                         mf->mat_nr = -1;
1959                                 }
1960                         }
1961                         else if (mf->mat_nr < me->totcol) {
1962                                 ma = me->mat[mf->mat_nr];
1963                                 
1964                                 /* no material create one if necessary */
1965                                 if (!ma) {
1966                                         /* find a new material and assign to the face */
1967                                         flag = encode_tfaceflag(tf, 1);
1968
1969                                         /* create/find a new material and assign to the face */
1970                                         if (check_tfaceneedmaterial(flag))
1971                                                 mf->mat_nr = convert_tfacenomaterial(main, me, tf, flag);
1972
1973                                         continue;
1974                                 }
1975
1976                                 /* we can't read from this if it comes from a library,
1977                                  * at doversion time: direct_link might not have happened on it,
1978                                  * so ma->mtex is not pointing to valid memory yet.
1979                                  * later we could, but it's better not */
1980                                 else if (ma->id.lib)
1981                                         continue;
1982                                 
1983                                 /* material already marked as disputed */
1984                                 else if (ma->game.flag == MAT_BGE_DISPUTED)
1985                                         continue;
1986
1987                                 /* found a material */
1988                                 else {
1989                                         flag = encode_tfaceflag(tf, ((fileload) ? 0 : 1));
1990
1991                                         /* first time changing this material */
1992                                         if (ma->game.flag == 0)
1993                                                 ma->game.flag = -flag;
1994                         
1995                                         /* mark material as disputed */
1996                                         else if (ma->game.flag != -flag) {
1997                                                 ma->game.flag = MAT_BGE_DISPUTED;
1998                                                 continue;
1999                                         }
2000                         
2001                                         /* material ok so far */
2002                                         else {
2003                                                 ma->game.flag = -flag;
2004                                                 
2005                                                 /* some people uses multitexture with TexFace by creating a texture
2006                                                  * channel which not necessarily the tf->tpage image. But the game engine
2007                                                  * was enabling it. Now it's required to set "Face Texture [Alpha] in the
2008                                                  * material settings. */
2009                                                 if (!fileload)
2010                                                         set_facetexture_flags(ma, tf->tpage);
2011                                         }
2012                                 }
2013                         }
2014                         else {
2015                                 continue;
2016                         }
2017                 }
2018
2019                 /* if we didn't have material slot and now we do, we need to
2020                  * make sure the materials are correct */
2021                 if (nomaterialslots) {
2022                         if (me->totcol > 0) {
2023                                 for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
2024                                         if (mf->mat_nr == -1) {
2025                                                 /* texface data for this face */
2026                                                 tf = ((MTFace *)cdl->data) + a;
2027                                                 mf->mat_nr = convert_tfacenomaterial(main, me, tf, encode_tfaceflag(tf, 1));
2028                                         }
2029                                 }
2030                         }
2031                         else {
2032                                 for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
2033                                         mf->mat_nr = 0;
2034                                 }
2035                         }
2036                 }
2037
2038         }
2039         
2040         /* 2nd part - conversion */
2041         /* skip library files */
2042
2043         /* we shouldn't loop through the materials created in the loop. make the loop stop at its original length) */
2044         for (ma = main->mat.first, a = 0; ma; ma = ma->id.next, a++) {
2045                 if (ma->id.lib) continue;
2046
2047                 /* disputed material */
2048                 if (ma->game.flag == MAT_BGE_DISPUTED) {
2049                         ma->game.flag = 0;
2050                         if (fileload) {
2051                                 printf("Warning: material \"%s\" skipped - to convert old game texface to material go to the Help menu.\n", ma->id.name + 2);
2052                                 nowarning = 0;
2053                         }
2054                         else {
2055                                 convert_tfacematerial(main, ma);
2056                         }
2057                         continue;
2058                 }
2059         
2060                 /* no conflicts in this material - 90% of cases
2061                  * convert from tface system to material */
2062                 else if (ma->game.flag < 0) {
2063                         decode_tfaceflag(ma, -(ma->game.flag), 1);
2064
2065                         /* material is good make sure all faces using
2066                          * this material are set to converted */
2067                         if (fileload) {
2068                                 for (me = main->mesh.first; me; me = me->id.next) {
2069                                         /* check if this mesh uses this material */
2070                                         for (a = 0; a < me->totcol; a++)
2071                                                 if (me->mat[a] == ma) break;
2072                                                 
2073                                         /* no material found */
2074                                         if (a == me->totcol) continue;
2075                         
2076                                         /* get the active tface layer */
2077                                         index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
2078                                         cdl = (index == -1) ? NULL : &me->fdata.layers[index];
2079                                         if (!cdl) continue;
2080                         
2081                                         /* loop over all the faces and stop at the ones that use the material*/
2082                                         for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
2083                                                 if (me->mat[mf->mat_nr] == ma) {
2084                                                         /* texface data for this face */
2085                                                         tf = ((MTFace *)cdl->data) + a;
2086                                                         tf->mode |= TF_CONVERTED;
2087                                                 }
2088                                         }
2089                                 }
2090                         }
2091                 }
2092                 /* material is not used by faces with texface
2093                  * set the default flag - do it only once */
2094                 else {
2095                         if (fileload) {
2096                                 ma->game.flag = GEMAT_BACKCULL;
2097                         }
2098                 }
2099         }
2100
2101         return nowarning;
2102 }
2103