Merging r58362 through r58463 from trunk into soc-2013-depsgraph_mt
[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                 if (ob->curve_cache) {
1279                         BKE_displist_free(&ob->curve_cache->disp);
1280                 }
1281         }
1282
1283         return TRUE;
1284 }
1285
1286
1287 /* r_col = current value, col = new value, (fac == 0) is no change */
1288 void ramp_blend(int type, float r_col[3], const float fac, const float col[3])
1289 {
1290         float tmp, facm = 1.0f - fac;
1291         
1292         switch (type) {
1293                 case MA_RAMP_BLEND:
1294                         r_col[0] = facm * (r_col[0]) + fac * col[0];
1295                         r_col[1] = facm * (r_col[1]) + fac * col[1];
1296                         r_col[2] = facm * (r_col[2]) + fac * col[2];
1297                         break;
1298                 case MA_RAMP_ADD:
1299                         r_col[0] += fac * col[0];
1300                         r_col[1] += fac * col[1];
1301                         r_col[2] += fac * col[2];
1302                         break;
1303                 case MA_RAMP_MULT:
1304                         r_col[0] *= (facm + fac * col[0]);
1305                         r_col[1] *= (facm + fac * col[1]);
1306                         r_col[2] *= (facm + fac * col[2]);
1307                         break;
1308                 case MA_RAMP_SCREEN:
1309                         r_col[0] = 1.0f - (facm + fac * (1.0f - col[0])) * (1.0f - r_col[0]);
1310                         r_col[1] = 1.0f - (facm + fac * (1.0f - col[1])) * (1.0f - r_col[1]);
1311                         r_col[2] = 1.0f - (facm + fac * (1.0f - col[2])) * (1.0f - r_col[2]);
1312                         break;
1313                 case MA_RAMP_OVERLAY:
1314                         if (r_col[0] < 0.5f)
1315                                 r_col[0] *= (facm + 2.0f * fac * col[0]);
1316                         else
1317                                 r_col[0] = 1.0f - (facm + 2.0f * fac * (1.0f - col[0])) * (1.0f - r_col[0]);
1318                         if (r_col[1] < 0.5f)
1319                                 r_col[1] *= (facm + 2.0f * fac * col[1]);
1320                         else
1321                                 r_col[1] = 1.0f - (facm + 2.0f * fac * (1.0f - col[1])) * (1.0f - r_col[1]);
1322                         if (r_col[2] < 0.5f)
1323                                 r_col[2] *= (facm + 2.0f * fac * col[2]);
1324                         else
1325                                 r_col[2] = 1.0f - (facm + 2.0f * fac * (1.0f - col[2])) * (1.0f - r_col[2]);
1326                         break;
1327                 case MA_RAMP_SUB:
1328                         r_col[0] -= fac * col[0];
1329                         r_col[1] -= fac * col[1];
1330                         r_col[2] -= fac * col[2];
1331                         break;
1332                 case MA_RAMP_DIV:
1333                         if (col[0] != 0.0f)
1334                                 r_col[0] = facm * (r_col[0]) + fac * (r_col[0]) / col[0];
1335                         if (col[1] != 0.0f)
1336                                 r_col[1] = facm * (r_col[1]) + fac * (r_col[1]) / col[1];
1337                         if (col[2] != 0.0f)
1338                                 r_col[2] = facm * (r_col[2]) + fac * (r_col[2]) / col[2];
1339                         break;
1340                 case MA_RAMP_DIFF:
1341                         r_col[0] = facm * (r_col[0]) + fac * fabsf(r_col[0] - col[0]);
1342                         r_col[1] = facm * (r_col[1]) + fac * fabsf(r_col[1] - col[1]);
1343                         r_col[2] = facm * (r_col[2]) + fac * fabsf(r_col[2] - col[2]);
1344                         break;
1345                 case MA_RAMP_DARK:
1346                         tmp = col[0] + ((1 - col[0]) * facm);
1347                         if (tmp < r_col[0]) r_col[0] = tmp;
1348                         tmp = col[1] + ((1 - col[1]) * facm);
1349                         if (tmp < r_col[1]) r_col[1] = tmp;
1350                         tmp = col[2] + ((1 - col[2]) * facm);
1351                         if (tmp < r_col[2]) r_col[2] = tmp;
1352                         break;
1353                 case MA_RAMP_LIGHT:
1354                         tmp = fac * col[0];
1355                         if (tmp > r_col[0]) r_col[0] = tmp;
1356                         tmp = fac * col[1];
1357                         if (tmp > r_col[1]) r_col[1] = tmp;
1358                         tmp = fac * col[2];
1359                         if (tmp > r_col[2]) r_col[2] = tmp;
1360                         break;
1361                 case MA_RAMP_DODGE:
1362                         if (r_col[0] != 0.0f) {
1363                                 tmp = 1.0f - fac * col[0];
1364                                 if (tmp <= 0.0f)
1365                                         r_col[0] = 1.0f;
1366                                 else if ((tmp = (r_col[0]) / tmp) > 1.0f)
1367                                         r_col[0] = 1.0f;
1368                                 else
1369                                         r_col[0] = tmp;
1370                         }
1371                         if (r_col[1] != 0.0f) {
1372                                 tmp = 1.0f - fac * col[1];
1373                                 if (tmp <= 0.0f)
1374                                         r_col[1] = 1.0f;
1375                                 else if ((tmp = (r_col[1]) / tmp) > 1.0f)
1376                                         r_col[1] = 1.0f;
1377                                 else
1378                                         r_col[1] = tmp;
1379                         }
1380                         if (r_col[2] != 0.0f) {
1381                                 tmp = 1.0f - fac * col[2];
1382                                 if (tmp <= 0.0f)
1383                                         r_col[2] = 1.0f;
1384                                 else if ((tmp = (r_col[2]) / tmp) > 1.0f)
1385                                         r_col[2] = 1.0f;
1386                                 else
1387                                         r_col[2] = tmp;
1388                         }
1389                         break;
1390                 case MA_RAMP_BURN:
1391                         tmp = facm + fac * col[0];
1392
1393                         if (tmp <= 0.0f)
1394                                 r_col[0] = 0.0f;
1395                         else if ((tmp = (1.0f - (1.0f - (r_col[0])) / tmp)) < 0.0f)
1396                                 r_col[0] = 0.0f;
1397                         else if (tmp > 1.0f)
1398                                 r_col[0] = 1.0f;
1399                         else
1400                                 r_col[0] = tmp;
1401
1402                         tmp = facm + fac * col[1];
1403                         if (tmp <= 0.0f)
1404                                 r_col[1] = 0.0f;
1405                         else if ((tmp = (1.0f - (1.0f - (r_col[1])) / tmp)) < 0.0f)
1406                                 r_col[1] = 0.0f;
1407                         else if (tmp > 1.0f)
1408                                 r_col[1] = 1.0f;
1409                         else
1410                                 r_col[1] = tmp;
1411
1412                         tmp = facm + fac * col[2];
1413                         if (tmp <= 0.0f)
1414                                 r_col[2] = 0.0f;
1415                         else if ((tmp = (1.0f - (1.0f - (r_col[2])) / tmp)) < 0.0f)
1416                                 r_col[2] = 0.0f;
1417                         else if (tmp > 1.0f)
1418                                 r_col[2] = 1.0f;
1419                         else
1420                                 r_col[2] = tmp;
1421                         break;
1422                 case MA_RAMP_HUE:
1423                 {
1424                         float rH, rS, rV;
1425                         float colH, colS, colV;
1426                         float tmpr, tmpg, tmpb;
1427                         rgb_to_hsv(col[0], col[1], col[2], &colH, &colS, &colV);
1428                         if (colS != 0) {
1429                                 rgb_to_hsv(r_col[0], r_col[1], r_col[2], &rH, &rS, &rV);
1430                                 hsv_to_rgb(colH, rS, rV, &tmpr, &tmpg, &tmpb);
1431                                 r_col[0] = facm * (r_col[0]) + fac * tmpr;
1432                                 r_col[1] = facm * (r_col[1]) + fac * tmpg;
1433                                 r_col[2] = facm * (r_col[2]) + fac * tmpb;
1434                         }
1435                         break;
1436                 }
1437                 case MA_RAMP_SAT:
1438                 {
1439                         float rH, rS, rV;
1440                         float colH, colS, colV;
1441                         rgb_to_hsv(r_col[0], r_col[1], r_col[2], &rH, &rS, &rV);
1442                         if (rS != 0) {
1443                                 rgb_to_hsv(col[0], col[1], col[2], &colH, &colS, &colV);
1444                                 hsv_to_rgb(rH, (facm * rS + fac * colS), rV, r_col + 0, r_col + 1, r_col + 2);
1445                         }
1446                         break;
1447                 }
1448                 case MA_RAMP_VAL:
1449                 {
1450                         float rH, rS, rV;
1451                         float colH, colS, colV;
1452                         rgb_to_hsv(r_col[0], r_col[1], r_col[2], &rH, &rS, &rV);
1453                         rgb_to_hsv(col[0], col[1], col[2], &colH, &colS, &colV);
1454                         hsv_to_rgb(rH, rS, (facm * rV + fac * colV), r_col + 0, r_col + 1, r_col + 2);
1455                         break;
1456                 }
1457                 case MA_RAMP_COLOR:
1458                 {
1459                         float rH, rS, rV;
1460                         float colH, colS, colV;
1461                         float tmpr, tmpg, tmpb;
1462                         rgb_to_hsv(col[0], col[1], col[2], &colH, &colS, &colV);
1463                         if (colS != 0) {
1464                                 rgb_to_hsv(r_col[0], r_col[1], r_col[2], &rH, &rS, &rV);
1465                                 hsv_to_rgb(colH, colS, rV, &tmpr, &tmpg, &tmpb);
1466                                 r_col[0] = facm * (r_col[0]) + fac * tmpr;
1467                                 r_col[1] = facm * (r_col[1]) + fac * tmpg;
1468                                 r_col[2] = facm * (r_col[2]) + fac * tmpb;
1469                         }
1470                         break;
1471                 }
1472                 case MA_RAMP_SOFT:
1473                 {
1474                         float scr, scg, scb;
1475
1476                         /* first calculate non-fac based Screen mix */
1477                         scr = 1.0f - (1.0f - col[0]) * (1.0f - r_col[0]);
1478                         scg = 1.0f - (1.0f - col[1]) * (1.0f - r_col[1]);
1479                         scb = 1.0f - (1.0f - col[2]) * (1.0f - r_col[2]);
1480
1481                         r_col[0] = facm * (r_col[0]) + fac * (((1.0f - r_col[0]) * col[0] * (r_col[0])) + (r_col[0] * scr));
1482                         r_col[1] = facm * (r_col[1]) + fac * (((1.0f - r_col[1]) * col[1] * (r_col[1])) + (r_col[1] * scg));
1483                         r_col[2] = facm * (r_col[2]) + fac * (((1.0f - r_col[2]) * col[2] * (r_col[2])) + (r_col[2] * scb));
1484                         break;
1485                 }
1486                 case MA_RAMP_LINEAR:
1487                         if (col[0] > 0.5f)
1488                                 r_col[0] = r_col[0] + fac * (2.0f * (col[0] - 0.5f));
1489                         else
1490                                 r_col[0] = r_col[0] + fac * (2.0f * (col[0]) - 1.0f);
1491                         if (col[1] > 0.5f)
1492                                 r_col[1] = r_col[1] + fac * (2.0f * (col[1] - 0.5f));
1493                         else
1494                                 r_col[1] = r_col[1] + fac * (2.0f * (col[1]) - 1.0f);
1495                         if (col[2] > 0.5f)
1496                                 r_col[2] = r_col[2] + fac * (2.0f * (col[2] - 0.5f));
1497                         else
1498                                 r_col[2] = r_col[2] + fac * (2.0f * (col[2]) - 1.0f);
1499                         break;
1500         }
1501 }
1502
1503 /**
1504  * \brief copy/paste buffer, if we had a proper py api that would be better
1505  * \note matcopybuf.nodetree does _NOT_ use ID's
1506  * \todo matcopybuf.nodetree's  node->id's are NOT validated, this will crash!
1507  */
1508 static Material matcopybuf;
1509 static short matcopied = 0;
1510
1511 void clear_matcopybuf(void)
1512 {
1513         memset(&matcopybuf, 0, sizeof(Material));
1514         matcopied = 0;
1515 }
1516
1517 void free_matcopybuf(void)
1518 {
1519         int a;
1520
1521         for (a = 0; a < MAX_MTEX; a++) {
1522                 if (matcopybuf.mtex[a]) {
1523                         MEM_freeN(matcopybuf.mtex[a]);
1524                         matcopybuf.mtex[a] = NULL;
1525                 }
1526         }
1527
1528         if (matcopybuf.ramp_col) MEM_freeN(matcopybuf.ramp_col);
1529         if (matcopybuf.ramp_spec) MEM_freeN(matcopybuf.ramp_spec);
1530
1531         matcopybuf.ramp_col = NULL;
1532         matcopybuf.ramp_spec = NULL;
1533
1534         if (matcopybuf.nodetree) {
1535                 ntreeFreeTree_ex(matcopybuf.nodetree, FALSE);
1536                 MEM_freeN(matcopybuf.nodetree);
1537                 matcopybuf.nodetree = NULL;
1538         }
1539
1540         matcopied = 0;
1541 }
1542
1543 void copy_matcopybuf(Material *ma)
1544 {
1545         int a;
1546         MTex *mtex;
1547
1548         if (matcopied)
1549                 free_matcopybuf();
1550
1551         memcpy(&matcopybuf, ma, sizeof(Material));
1552         if (matcopybuf.ramp_col) matcopybuf.ramp_col = MEM_dupallocN(matcopybuf.ramp_col);
1553         if (matcopybuf.ramp_spec) matcopybuf.ramp_spec = MEM_dupallocN(matcopybuf.ramp_spec);
1554
1555         for (a = 0; a < MAX_MTEX; a++) {
1556                 mtex = matcopybuf.mtex[a];
1557                 if (mtex) {
1558                         matcopybuf.mtex[a] = MEM_dupallocN(mtex);
1559                 }
1560         }
1561         matcopybuf.nodetree = ntreeCopyTree_ex(ma->nodetree, FALSE);
1562         matcopybuf.preview = NULL;
1563         matcopybuf.gpumaterial.first = matcopybuf.gpumaterial.last = NULL;
1564         matcopied = 1;
1565 }
1566
1567 void paste_matcopybuf(Material *ma)
1568 {
1569         int a;
1570         MTex *mtex;
1571         ID id;
1572
1573         if (matcopied == 0)
1574                 return;
1575         /* free current mat */
1576         if (ma->ramp_col) MEM_freeN(ma->ramp_col);
1577         if (ma->ramp_spec) MEM_freeN(ma->ramp_spec);
1578         for (a = 0; a < MAX_MTEX; a++) {
1579                 mtex = ma->mtex[a];
1580                 if (mtex && mtex->tex) mtex->tex->id.us--;
1581                 if (mtex) MEM_freeN(mtex);
1582         }
1583
1584         if (ma->nodetree) {
1585                 ntreeFreeTree(ma->nodetree);
1586                 MEM_freeN(ma->nodetree);
1587         }
1588
1589         GPU_material_free(ma);
1590
1591         id = (ma->id);
1592         memcpy(ma, &matcopybuf, sizeof(Material));
1593         (ma->id) = id;
1594
1595         if (matcopybuf.ramp_col) ma->ramp_col = MEM_dupallocN(matcopybuf.ramp_col);
1596         if (matcopybuf.ramp_spec) ma->ramp_spec = MEM_dupallocN(matcopybuf.ramp_spec);
1597
1598         for (a = 0; a < MAX_MTEX; a++) {
1599                 mtex = ma->mtex[a];
1600                 if (mtex) {
1601                         ma->mtex[a] = MEM_dupallocN(mtex);
1602                         if (mtex->tex) {
1603                                 /* first check this is in main (we may have loaded another file) [#35500] */
1604                                 if (BLI_findindex(&G.main->tex, mtex->tex) != -1) {
1605                                         id_us_plus((ID *)mtex->tex);
1606                                 }
1607                                 else {
1608                                         ma->mtex[a]->tex = NULL;
1609                                 }
1610                         }
1611                 }
1612         }
1613
1614         ma->nodetree = ntreeCopyTree_ex(matcopybuf.nodetree, FALSE);
1615 }
1616
1617
1618 /*********************** texface to material convert functions **********************/
1619 /* encode all the TF information into a single int */
1620 static int encode_tfaceflag(MTFace *tf, int convertall)
1621 {
1622         /* calculate the flag */
1623         int flag = tf->mode;
1624
1625         /* options that change the material offline render */
1626         if (!convertall) {
1627                 flag &= ~TF_OBCOL;
1628         }
1629
1630         /* clean flags that are not being converted */
1631         flag &= ~TF_TEX;
1632         flag &= ~TF_SHAREDVERT;
1633         flag &= ~TF_SHAREDCOL;
1634         flag &= ~TF_CONVERTED;
1635
1636         /* light tface flag is ignored in GLSL mode */
1637         flag &= ~TF_LIGHT;
1638         
1639         /* 15 is how big the flag can be - hardcoded here and in decode_tfaceflag() */
1640         flag |= tf->transp << 15;
1641         
1642         /* increase 1 so flag 0 is different than no flag yet */
1643         return flag + 1;
1644 }
1645
1646 /* set the material options based in the tface flag */
1647 static void decode_tfaceflag(Material *ma, int flag, int convertall)
1648 {
1649         int alphablend;
1650         GameSettings *game = &ma->game;
1651
1652         /* flag is shifted in 1 to make 0 != no flag yet (see encode_tfaceflag) */
1653         flag -= 1;
1654
1655         alphablend = flag >> 15;  /* encoded in the encode_tfaceflag function */
1656         (*game).flag = 0;
1657         
1658         /* General Material Options */
1659         if ((flag & TF_DYNAMIC) == 0) (*game).flag    |= GEMAT_NOPHYSICS;
1660         
1661         /* Material Offline Rendering Properties */
1662         if (convertall) {
1663                 if (flag & TF_OBCOL) ma->shade_flag |= MA_OBCOLOR;
1664         }
1665         
1666         /* Special Face Properties */
1667         if ((flag & TF_TWOSIDE) == 0) (*game).flag |= GEMAT_BACKCULL;
1668         if (flag & TF_INVISIBLE) (*game).flag |= GEMAT_INVISIBLE;
1669         if (flag & TF_BMFONT) (*game).flag |= GEMAT_TEXT;
1670         
1671         /* Face Orientation */
1672         if (flag & TF_BILLBOARD) (*game).face_orientation |= GEMAT_HALO;
1673         else if (flag & TF_BILLBOARD2) (*game).face_orientation |= GEMAT_BILLBOARD;
1674         else if (flag & TF_SHADOW) (*game).face_orientation |= GEMAT_SHADOW;
1675         
1676         /* Alpha Blend */
1677         if (flag & TF_ALPHASORT && ELEM(alphablend, TF_ALPHA, TF_ADD)) (*game).alpha_blend = GEMAT_ALPHA_SORT;
1678         else if (alphablend & TF_ALPHA) (*game).alpha_blend = GEMAT_ALPHA;
1679         else if (alphablend & TF_ADD) (*game).alpha_blend = GEMAT_ADD;
1680         else if (alphablend & TF_CLIP) (*game).alpha_blend = GEMAT_CLIP;
1681 }
1682
1683 /* boolean check to see if the mesh needs a material */
1684 static int check_tfaceneedmaterial(int flag)
1685 {
1686         /* check if the flags we have are not deprecated != than default material options
1687          * also if only flags are visible and collision see if all objects using this mesh have this option in physics */
1688
1689         /* flag is shifted in 1 to make 0 != no flag yet (see encode_tfaceflag) */
1690         flag -= 1;
1691
1692         /* deprecated flags */
1693         flag &= ~TF_OBCOL;
1694         flag &= ~TF_SHAREDVERT;
1695         flag &= ~TF_SHAREDCOL;
1696
1697         /* light tface flag is ignored in GLSL mode */
1698         flag &= ~TF_LIGHT;
1699         
1700         /* automatic detected if tex image has alpha */
1701         flag &= ~(TF_ALPHA << 15);
1702         /* automatic detected if using texture */
1703         flag &= ~TF_TEX;
1704
1705         /* settings for the default NoMaterial */
1706         if (flag == TF_DYNAMIC)
1707                 return 0;
1708
1709         else
1710                 return 1;
1711 }
1712
1713 /* return number of digits of an integer */
1714 /* XXX to be optmized or replaced by an equivalent blender internal function */
1715 static int integer_getdigits(int number)
1716 {
1717         int i = 0;
1718         if (number == 0) return 1;
1719
1720         while (number != 0) {
1721                 number = (int)(number / 10);
1722                 i++;
1723         }
1724         return i;
1725 }
1726
1727 static void calculate_tface_materialname(char *matname, char *newname, int flag)
1728 {
1729         /* if flag has only light and collision and material matches those values
1730          * you can do strcpy(name, mat_name);
1731          * otherwise do: */
1732         int digits = integer_getdigits(flag);
1733         /* clamp the old name, remove the MA prefix and add the .TF.flag suffix
1734          * e.g. matname = "MALoooooooooooooongName"; newname = "Loooooooooooooon.TF.2" */
1735         BLI_snprintf(newname, MAX_ID_NAME, "%.*s.TF.%0*d", MAX_ID_NAME - (digits + 5), matname, digits, flag);
1736 }
1737
1738 /* returns -1 if no match */
1739 static short mesh_getmaterialnumber(Mesh *me, Material *ma)
1740 {
1741         short a;
1742
1743         for (a = 0; a < me->totcol; a++) {
1744                 if (me->mat[a] == ma) {
1745                         return a;
1746                 }
1747         }
1748
1749         return -1;
1750 }
1751
1752 /* append material */
1753 static short mesh_addmaterial(Mesh *me, Material *ma)
1754 {
1755         material_append_id(&me->id, NULL);
1756         me->mat[me->totcol - 1] = ma;
1757
1758         id_us_plus(&ma->id);
1759
1760         return me->totcol - 1;
1761 }
1762
1763 static void set_facetexture_flags(Material *ma, Image *image)
1764 {
1765         if (image) {
1766                 ma->mode |= MA_FACETEXTURE;
1767                 /* we could check if the texture has alpha, but then more meshes sharing the same
1768                  * material may need it. Let's make it simple. */
1769                 if (BKE_image_has_alpha(image))
1770                         ma->mode |= MA_FACETEXTURE_ALPHA;
1771         }
1772 }
1773
1774 /* returns material number */
1775 static short convert_tfacenomaterial(Main *main, Mesh *me, MTFace *tf, int flag)
1776 {
1777         Material *ma;
1778         char idname[MAX_ID_NAME];
1779         short mat_nr = -1;
1780         
1781         /* new material, the name uses the flag*/
1782         BLI_snprintf(idname, sizeof(idname), "MAMaterial.TF.%0*d", integer_getdigits(flag), flag);
1783
1784         if ((ma = BLI_findstring(&main->mat, idname + 2, offsetof(ID, name) + 2))) {
1785                 mat_nr = mesh_getmaterialnumber(me, ma);
1786                 /* assign the material to the mesh */
1787                 if (mat_nr == -1) mat_nr = mesh_addmaterial(me, ma);
1788
1789                 /* if needed set "Face Textures [Alpha]" Material options */
1790                 set_facetexture_flags(ma, tf->tpage);
1791         }
1792         /* create a new material */
1793         else {
1794                 ma = BKE_material_add(main, idname + 2);
1795
1796                 if (ma) {
1797                         printf("TexFace Convert: Material \"%s\" created.\n", idname + 2);
1798                         mat_nr = mesh_addmaterial(me, ma);
1799                         
1800                         /* if needed set "Face Textures [Alpha]" Material options */
1801                         set_facetexture_flags(ma, tf->tpage);
1802
1803                         decode_tfaceflag(ma, flag, 1);
1804                         /* the final decoding will happen after, outside the main loop
1805                          * for now store the flag into the material and change light/tex/collision
1806                          * store the flag as a negative number */
1807                         ma->game.flag = -flag;
1808                         id_us_min((ID *)ma);
1809                 }
1810                 else {
1811                         printf("Error: Unable to create Material \"%s\" for Mesh \"%s\".", idname + 2, me->id.name + 2);
1812                 }
1813         }
1814
1815         /* set as converted, no need to go bad to this face */
1816         tf->mode |= TF_CONVERTED;
1817         return mat_nr;
1818 }
1819
1820 /* Function to fully convert materials */
1821 static void convert_tfacematerial(Main *main, Material *ma)
1822 {
1823         Mesh *me;
1824         Material *mat_new;
1825         MFace *mf;
1826         MTFace *tf;
1827         int flag, index;
1828         int a;
1829         short mat_nr;
1830         CustomDataLayer *cdl;
1831         char idname[MAX_ID_NAME];
1832
1833         for (me = main->mesh.first; me; me = me->id.next) {
1834                 /* check if this mesh uses this material */
1835                 for (a = 0; a < me->totcol; a++)
1836                         if (me->mat[a] == ma) break;
1837                         
1838                 /* no material found */
1839                 if (a == me->totcol) continue;
1840
1841                 /* get the active tface layer */
1842                 index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
1843                 cdl = (index == -1) ? NULL : &me->fdata.layers[index];
1844                 if (!cdl) continue;
1845
1846                 /* loop over all the faces and stop at the ones that use the material*/
1847                 for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
1848                         if (me->mat[mf->mat_nr] != ma) continue;
1849
1850                         /* texface data for this face */
1851                         tf = ((MTFace *)cdl->data) + a;
1852                         flag = encode_tfaceflag(tf, 1);
1853
1854                         /* the name of the new material */
1855                         calculate_tface_materialname(ma->id.name, (char *)&idname, flag);
1856
1857                         if ((mat_new = BLI_findstring(&main->mat, idname + 2, offsetof(ID, name) + 2))) {
1858                                 /* material already existent, see if the mesh has it */
1859                                 mat_nr = mesh_getmaterialnumber(me, mat_new);
1860                                 /* material is not in the mesh, add it */
1861                                 if (mat_nr == -1) mat_nr = mesh_addmaterial(me, mat_new);
1862                         }
1863                         /* create a new material */
1864                         else {
1865                                 mat_new = BKE_material_copy(ma);
1866                                 if (mat_new) {
1867                                         /* rename the material*/
1868                                         BLI_strncpy(mat_new->id.name, idname, sizeof(mat_new->id.name));
1869                                         id_us_min((ID *)mat_new);
1870
1871                                         mat_nr = mesh_addmaterial(me, mat_new);
1872                                         decode_tfaceflag(mat_new, flag, 1);
1873                                 }
1874                                 else {
1875                                         printf("Error: Unable to create Material \"%s\" for Mesh \"%s.", idname + 2, me->id.name + 2);
1876                                         mat_nr = mf->mat_nr;
1877                                         continue;
1878                                 }
1879                         }
1880                         
1881                         /* if the material has a texture but no texture channel
1882                          * set "Face Textures [Alpha]" Material options 
1883                          * actually we need to run it always, because of old behavior
1884                          * of using face texture if any texture channel was present (multitex) */
1885                         //if ((!mat_new->mtex[0]) && (!mat_new->mtex[0]->tex))
1886                         set_facetexture_flags(mat_new, tf->tpage);
1887
1888                         /* set the material number to the face*/
1889                         mf->mat_nr = mat_nr;
1890                 }
1891                 /* remove material from mesh */
1892                 for (a = 0; a < me->totcol; )
1893                         if (me->mat[a] == ma) material_pop_id(&me->id, a, 1); else a++;
1894         }
1895 }
1896
1897
1898 #define MAT_BGE_DISPUTED -99999
1899
1900 int do_version_tface(Main *main, int fileload)
1901 {
1902         Mesh *me;
1903         Material *ma;
1904         MFace *mf;
1905         MTFace *tf;
1906         CustomDataLayer *cdl;
1907         int a;
1908         int flag;
1909         int index;
1910
1911         /* sometimes mesh has no materials but will need a new one. In those
1912          * cases we need to ignore the mf->mat_nr and only look at the face
1913          * mode because it can be zero as uninitialized or the 1st created material
1914          */
1915         int nomaterialslots;
1916
1917         /* alert to user to check the console */
1918         int nowarning = 1;
1919
1920         /* mark all the materials to conversion with a flag
1921          * if there is tface create a complete flag for that storing in flag
1922          * if there is tface and flag > 0: creates a new flag based on this face
1923          * if flags are different set flag to -1  
1924          */
1925         
1926         /* 1st part: marking mesh materials to update */
1927         for (me = main->mesh.first; me; me = me->id.next) {
1928                 if (me->id.lib) continue;
1929
1930                 /* get the active tface layer */
1931                 index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
1932                 cdl = (index == -1) ? NULL : &me->fdata.layers[index];
1933                 if (!cdl) continue;
1934
1935                 nomaterialslots = (me->totcol == 0 ? 1 : 0);
1936                 
1937                 /* loop over all the faces*/
1938                 for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
1939                         /* texface data for this face */
1940                         tf = ((MTFace *)cdl->data) + a;
1941
1942                         /* conversion should happen only once */
1943                         if (fileload)
1944                                 tf->mode &= ~TF_CONVERTED;
1945                         else {
1946                                 if ((tf->mode & TF_CONVERTED)) continue;
1947                                 else tf->mode |= TF_CONVERTED;
1948                         }
1949                         
1950                         /* no material slots */
1951                         if (nomaterialslots) {
1952                                 flag = encode_tfaceflag(tf, 1);
1953                                 
1954                                 /* create/find a new material and assign to the face */
1955                                 if (check_tfaceneedmaterial(flag)) {
1956                                         mf->mat_nr = convert_tfacenomaterial(main, me, tf, flag);
1957                                 }
1958                                 /* else mark them as no-material to be reverted to 0 later */
1959                                 else {
1960                                         mf->mat_nr = -1;
1961                                 }
1962                         }
1963                         else if (mf->mat_nr < me->totcol) {
1964                                 ma = me->mat[mf->mat_nr];
1965                                 
1966                                 /* no material create one if necessary */
1967                                 if (!ma) {
1968                                         /* find a new material and assign to the face */
1969                                         flag = encode_tfaceflag(tf, 1);
1970
1971                                         /* create/find a new material and assign to the face */
1972                                         if (check_tfaceneedmaterial(flag))
1973                                                 mf->mat_nr = convert_tfacenomaterial(main, me, tf, flag);
1974
1975                                         continue;
1976                                 }
1977
1978                                 /* we can't read from this if it comes from a library,
1979                                  * at doversion time: direct_link might not have happened on it,
1980                                  * so ma->mtex is not pointing to valid memory yet.
1981                                  * later we could, but it's better not */
1982                                 else if (ma->id.lib)
1983                                         continue;
1984                                 
1985                                 /* material already marked as disputed */
1986                                 else if (ma->game.flag == MAT_BGE_DISPUTED)
1987                                         continue;
1988
1989                                 /* found a material */
1990                                 else {
1991                                         flag = encode_tfaceflag(tf, ((fileload) ? 0 : 1));
1992
1993                                         /* first time changing this material */
1994                                         if (ma->game.flag == 0)
1995                                                 ma->game.flag = -flag;
1996                         
1997                                         /* mark material as disputed */
1998                                         else if (ma->game.flag != -flag) {
1999                                                 ma->game.flag = MAT_BGE_DISPUTED;
2000                                                 continue;
2001                                         }
2002                         
2003                                         /* material ok so far */
2004                                         else {
2005                                                 ma->game.flag = -flag;
2006                                                 
2007                                                 /* some people uses multitexture with TexFace by creating a texture
2008                                                  * channel which not necessarily the tf->tpage image. But the game engine
2009                                                  * was enabling it. Now it's required to set "Face Texture [Alpha] in the
2010                                                  * material settings. */
2011                                                 if (!fileload)
2012                                                         set_facetexture_flags(ma, tf->tpage);
2013                                         }
2014                                 }
2015                         }
2016                         else {
2017                                 continue;
2018                         }
2019                 }
2020
2021                 /* if we didn't have material slot and now we do, we need to
2022                  * make sure the materials are correct */
2023                 if (nomaterialslots) {
2024                         if (me->totcol > 0) {
2025                                 for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
2026                                         if (mf->mat_nr == -1) {
2027                                                 /* texface data for this face */
2028                                                 tf = ((MTFace *)cdl->data) + a;
2029                                                 mf->mat_nr = convert_tfacenomaterial(main, me, tf, encode_tfaceflag(tf, 1));
2030                                         }
2031                                 }
2032                         }
2033                         else {
2034                                 for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
2035                                         mf->mat_nr = 0;
2036                                 }
2037                         }
2038                 }
2039
2040         }
2041         
2042         /* 2nd part - conversion */
2043         /* skip library files */
2044
2045         /* we shouldn't loop through the materials created in the loop. make the loop stop at its original length) */
2046         for (ma = main->mat.first, a = 0; ma; ma = ma->id.next, a++) {
2047                 if (ma->id.lib) continue;
2048
2049                 /* disputed material */
2050                 if (ma->game.flag == MAT_BGE_DISPUTED) {
2051                         ma->game.flag = 0;
2052                         if (fileload) {
2053                                 printf("Warning: material \"%s\" skipped - to convert old game texface to material go to the Help menu.\n", ma->id.name + 2);
2054                                 nowarning = 0;
2055                         }
2056                         else {
2057                                 convert_tfacematerial(main, ma);
2058                         }
2059                         continue;
2060                 }
2061         
2062                 /* no conflicts in this material - 90% of cases
2063                  * convert from tface system to material */
2064                 else if (ma->game.flag < 0) {
2065                         decode_tfaceflag(ma, -(ma->game.flag), 1);
2066
2067                         /* material is good make sure all faces using
2068                          * this material are set to converted */
2069                         if (fileload) {
2070                                 for (me = main->mesh.first; me; me = me->id.next) {
2071                                         /* check if this mesh uses this material */
2072                                         for (a = 0; a < me->totcol; a++)
2073                                                 if (me->mat[a] == ma) break;
2074                                                 
2075                                         /* no material found */
2076                                         if (a == me->totcol) continue;
2077                         
2078                                         /* get the active tface layer */
2079                                         index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
2080                                         cdl = (index == -1) ? NULL : &me->fdata.layers[index];
2081                                         if (!cdl) continue;
2082                         
2083                                         /* loop over all the faces and stop at the ones that use the material*/
2084                                         for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
2085                                                 if (me->mat[mf->mat_nr] == ma) {
2086                                                         /* texface data for this face */
2087                                                         tf = ((MTFace *)cdl->data) + a;
2088                                                         tf->mode |= TF_CONVERTED;
2089                                                 }
2090                                         }
2091                                 }
2092                         }
2093                 }
2094                 /* material is not used by faces with texface
2095                  * set the default flag - do it only once */
2096                 else {
2097                         if (fileload) {
2098                                 ma->game.flag = GEMAT_BACKCULL;
2099                         }
2100                 }
2101         }
2102
2103         return nowarning;
2104 }
2105