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