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