sim: Remove "continue physics" code
[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 void resize_object_material(Object *ob, const short totcol)
685 {
686         Material **newmatar;
687         char *newmatbits;
688
689         if (totcol == 0) {
690                 if (ob->totcol) {
691                         MEM_freeN(ob->mat);
692                         MEM_freeN(ob->matbits);
693                         ob->mat = NULL;
694                         ob->matbits = NULL;
695                 }
696         }
697         else if (ob->totcol < totcol) {
698                 newmatar = MEM_callocN(sizeof(void *) * totcol, "newmatar");
699                 newmatbits = MEM_callocN(sizeof(char) * totcol, "newmatbits");
700                 if (ob->totcol) {
701                         memcpy(newmatar, ob->mat, sizeof(void *) * ob->totcol);
702                         memcpy(newmatbits, ob->matbits, sizeof(char) * ob->totcol);
703                         MEM_freeN(ob->mat);
704                         MEM_freeN(ob->matbits);
705                 }
706                 ob->mat = newmatar;
707                 ob->matbits = newmatbits;
708         }
709         ob->totcol = totcol;
710         if (ob->totcol && ob->actcol == 0) ob->actcol = 1;
711         if (ob->actcol > ob->totcol) ob->actcol = ob->totcol;
712 }
713
714 void test_object_materials(ID *id)
715 {
716         /* make the ob mat-array same size as 'ob->data' mat-array */
717         Object *ob;
718         short *totcol;
719
720         if (id == NULL || (totcol = give_totcolp_id(id)) == NULL) {
721                 return;
722         }
723
724         for (ob = G.main->object.first; ob; ob = ob->id.next) {
725                 if (ob->data == id) {
726                         resize_object_material(ob, *totcol);
727                 }
728         }
729 }
730
731 void assign_material_id(ID *id, Material *ma, short act)
732 {
733         Material *mao, **matar, ***matarar;
734         short *totcolp;
735
736         if (act > MAXMAT) return;
737         if (act < 1) act = 1;
738
739         /* prevent crashing when using accidentally */
740         BLI_assert(id->lib == NULL);
741         if (id->lib) return;
742
743         /* test arraylens */
744
745         totcolp = give_totcolp_id(id);
746         matarar = give_matarar_id(id);
747
748         if (totcolp == NULL || matarar == NULL) return;
749
750         if (act > *totcolp) {
751                 matar = MEM_callocN(sizeof(void *) * act, "matarray1");
752
753                 if (*totcolp) {
754                         memcpy(matar, *matarar, sizeof(void *) * (*totcolp));
755                         MEM_freeN(*matarar);
756                 }
757
758                 *matarar = matar;
759                 *totcolp = act;
760         }
761
762         /* in data */
763         mao = (*matarar)[act - 1];
764         if (mao) mao->id.us--;
765         (*matarar)[act - 1] = ma;
766
767         if (ma)
768                 id_us_plus((ID *)ma);
769
770         test_object_materials(id);
771 }
772
773 void assign_material(Object *ob, Material *ma, short act, int assign_type)
774 {
775         Material *mao, **matar, ***matarar;
776         char *matbits;
777         short *totcolp;
778         char bit = 0;
779
780         if (act > MAXMAT) return;
781         if (act < 1) act = 1;
782         
783         /* prevent crashing when using accidentally */
784         BLI_assert(ob->id.lib == NULL);
785         if (ob->id.lib) return;
786         
787         /* test arraylens */
788         
789         totcolp = give_totcolp(ob);
790         matarar = give_matarar(ob);
791         
792         if (totcolp == NULL || matarar == NULL) return;
793         
794         if (act > *totcolp) {
795                 matar = MEM_callocN(sizeof(void *) * act, "matarray1");
796
797                 if (*totcolp) {
798                         memcpy(matar, *matarar, sizeof(void *) * (*totcolp));
799                         MEM_freeN(*matarar);
800                 }
801
802                 *matarar = matar;
803                 *totcolp = act;
804         }
805
806         /* Determine the object/mesh linking */
807         if (assign_type == BKE_MAT_ASSIGN_USERPREF && ob->totcol && ob->actcol) {
808                 /* copy from previous material */
809                 bit = ob->matbits[ob->actcol - 1];
810         }
811         else {
812                 switch (assign_type) {
813                         case BKE_MAT_ASSIGN_OBDATA:
814                                 bit = 0;
815                                 break;
816                         case BKE_MAT_ASSIGN_OBJECT:
817                                 bit = 1;
818                                 break;
819                         case BKE_MAT_ASSIGN_USERPREF:
820                         default:
821                                 bit = (U.flag & USER_MAT_ON_OB) ? 1 : 0;
822                                 break;
823                 }
824         }
825
826         if (act > ob->totcol) {
827                 /* Need more space in the material arrays */
828                 matar = MEM_callocN(sizeof(void *) * act, "matarray2");
829                 matbits = MEM_callocN(sizeof(char) * act, "matbits1");
830                 if (ob->totcol) {
831                         memcpy(matar, ob->mat, sizeof(void *) * ob->totcol);
832                         memcpy(matbits, ob->matbits, sizeof(char) * (*totcolp));
833                         MEM_freeN(ob->mat);
834                         MEM_freeN(ob->matbits);
835                 }
836                 ob->mat = matar;
837                 ob->matbits = matbits;
838                 ob->totcol = act;
839         }
840         
841         /* do it */
842
843         ob->matbits[act - 1] = bit;
844         if (bit == 1) {   /* in object */
845                 mao = ob->mat[act - 1];
846                 if (mao) mao->id.us--;
847                 ob->mat[act - 1] = ma;
848         }
849         else {  /* in data */
850                 mao = (*matarar)[act - 1];
851                 if (mao) mao->id.us--;
852                 (*matarar)[act - 1] = ma;
853         }
854
855         if (ma)
856                 id_us_plus((ID *)ma);
857         test_object_materials(ob->data);
858 }
859
860 /* XXX - this calls many more update calls per object then are needed, could be optimized */
861 void assign_matarar(struct Object *ob, struct Material ***matar, short totcol)
862 {
863         int actcol_orig = ob->actcol;
864         short i;
865
866         while (object_remove_material_slot(ob)) {}
867
868         /* now we have the right number of slots */
869         for (i = 0; i < totcol; i++)
870                 assign_material(ob, (*matar)[i], i + 1, BKE_MAT_ASSIGN_USERPREF);
871
872         if (actcol_orig > ob->totcol)
873                 actcol_orig = ob->totcol;
874
875         ob->actcol = actcol_orig;
876 }
877
878
879 short find_material_index(Object *ob, Material *ma)
880 {
881         Material ***matarar;
882         short a, *totcolp;
883         
884         if (ma == NULL) return 0;
885         
886         totcolp = give_totcolp(ob);
887         matarar = give_matarar(ob);
888         
889         if (totcolp == NULL || matarar == NULL) return 0;
890         
891         for (a = 0; a < *totcolp; a++)
892                 if ((*matarar)[a] == ma)
893                         break;
894         if (a < *totcolp)
895                 return a + 1;
896         return 0;
897 }
898
899 int object_add_material_slot(Object *ob)
900 {
901         if (ob == NULL) return FALSE;
902         if (ob->totcol >= MAXMAT) return FALSE;
903         
904         assign_material(ob, NULL, ob->totcol + 1, BKE_MAT_ASSIGN_USERPREF);
905         ob->actcol = ob->totcol;
906         return TRUE;
907 }
908
909 static void do_init_render_material(Material *ma, int r_mode, float *amb)
910 {
911         MTex *mtex;
912         int a, needuv = 0, needtang = 0;
913         
914         if (ma->flarec == 0) ma->flarec = 1;
915
916         /* add all texcoflags from mtex, texco and mapto were cleared in advance */
917         for (a = 0; a < MAX_MTEX; a++) {
918                 
919                 /* separate tex switching */
920                 if (ma->septex & (1 << a)) continue;
921
922                 mtex = ma->mtex[a];
923                 if (mtex && mtex->tex && (mtex->tex->type | (mtex->tex->use_nodes && mtex->tex->nodetree) )) {
924                         
925                         ma->texco |= mtex->texco;
926                         ma->mapto |= mtex->mapto;
927
928                         /* always get derivatives for these textures */
929                         if (ELEM(mtex->tex->type, TEX_IMAGE, TEX_ENVMAP)) ma->texco |= TEXCO_OSA;
930                         else if (mtex->texflag & (MTEX_COMPAT_BUMP | MTEX_3TAP_BUMP | MTEX_5TAP_BUMP | MTEX_BICUBIC_BUMP)) ma->texco |= TEXCO_OSA;
931                         
932                         if (ma->texco & (TEXCO_ORCO | TEXCO_REFL | TEXCO_NORM | TEXCO_STRAND | TEXCO_STRESS)) needuv = 1;
933                         else if (ma->texco & (TEXCO_GLOB | TEXCO_UV | TEXCO_OBJECT | TEXCO_SPEED)) needuv = 1;
934                         else if (ma->texco & (TEXCO_LAVECTOR | TEXCO_VIEW)) needuv = 1;
935
936                         if ((ma->mapto & MAP_NORM) && (mtex->normapspace == MTEX_NSPACE_TANGENT))
937                                 needtang = 1;
938                 }
939         }
940
941         if (needtang) ma->mode |= MA_NORMAP_TANG;
942         else ma->mode &= ~MA_NORMAP_TANG;
943         
944         if (ma->mode & (MA_VERTEXCOL | MA_VERTEXCOLP | MA_FACETEXTURE)) {
945                 needuv = 1;
946                 if (r_mode & R_OSA) ma->texco |= TEXCO_OSA;     /* for texfaces */
947         }
948         if (needuv) ma->texco |= NEED_UV;
949         
950         /* since the raytracer doesnt recalc O structs for each ray, we have to preset them all */
951         if (r_mode & R_RAYTRACE) {
952                 if ((ma->mode & (MA_RAYMIRROR | MA_SHADOW_TRA)) || ((ma->mode & MA_TRANSP) && (ma->mode & MA_RAYTRANSP))) {
953                         ma->texco |= NEED_UV | TEXCO_ORCO | TEXCO_REFL | TEXCO_NORM;
954                         if (r_mode & R_OSA) ma->texco |= TEXCO_OSA;
955                 }
956         }
957         
958         if (amb) {
959                 ma->ambr = ma->amb * amb[0];
960                 ma->ambg = ma->amb * amb[1];
961                 ma->ambb = ma->amb * amb[2];
962         }
963         /* will become or-ed result of all node modes */
964         ma->mode_l = ma->mode;
965         ma->mode_l &= ~MA_SHLESS;
966
967         if (ma->strand_surfnor > 0.0f)
968                 ma->mode_l |= MA_STR_SURFDIFF;
969
970         /* parses the geom+tex nodes */
971         if (ma->nodetree && ma->use_nodes)
972                 ntreeShaderGetTexcoMode(ma->nodetree, r_mode, &ma->texco, &ma->mode_l);
973
974         /* local group override */
975         if ((ma->shade_flag & MA_GROUP_LOCAL) && ma->id.lib && ma->group && ma->group->id.lib) {
976                 Group *group;
977
978                 for (group = G.main->group.first; group; group = group->id.next) {
979                         if (!group->id.lib && strcmp(group->id.name, ma->group->id.name) == 0) {
980                                 ma->group = group;
981                         }
982                 }
983         }
984 }
985
986 static void init_render_nodetree(bNodeTree *ntree, Material *basemat, int r_mode, float *amb)
987 {
988         bNode *node;
989         
990         for (node = ntree->nodes.first; node; node = node->next) {
991                 if (node->id) {
992                         if (GS(node->id->name) == ID_MA) {
993                                 Material *ma = (Material *)node->id;
994                                 if (ma != basemat) {
995                                         do_init_render_material(ma, r_mode, amb);
996                                         basemat->texco |= ma->texco;
997                                         basemat->mode_l |= ma->mode_l & ~(MA_TRANSP | MA_ZTRANSP | MA_RAYTRANSP);
998                                 }
999                         }
1000                         else if (node->type == NODE_GROUP)
1001                                 init_render_nodetree((bNodeTree *)node->id, basemat, r_mode, amb);
1002                 }
1003         }
1004 }
1005
1006 void init_render_material(Material *mat, int r_mode, float *amb)
1007 {
1008         
1009         do_init_render_material(mat, r_mode, amb);
1010         
1011         if (mat->nodetree && mat->use_nodes) {
1012                 init_render_nodetree(mat->nodetree, mat, r_mode, amb);
1013                 
1014                 if (!mat->nodetree->execdata)
1015                         mat->nodetree->execdata = ntreeShaderBeginExecTree(mat->nodetree, 1);
1016         }
1017 }
1018
1019 void init_render_materials(Main *bmain, int r_mode, float *amb)
1020 {
1021         Material *ma;
1022         
1023         /* clear these flags before going over materials, to make sure they
1024          * are cleared only once, otherwise node materials contained in other
1025          * node materials can go wrong */
1026         for (ma = bmain->mat.first; ma; ma = ma->id.next) {
1027                 if (ma->id.us) {
1028                         ma->texco = 0;
1029                         ma->mapto = 0;
1030                 }
1031         }
1032
1033         /* two steps, first initialize, then or the flags for layers */
1034         for (ma = bmain->mat.first; ma; ma = ma->id.next) {
1035                 /* is_used flag comes back in convertblender.c */
1036                 ma->flag &= ~MA_IS_USED;
1037                 if (ma->id.us) 
1038                         init_render_material(ma, r_mode, amb);
1039         }
1040         
1041         do_init_render_material(&defmaterial, r_mode, amb);
1042 }
1043
1044 /* only needed for nodes now */
1045 void end_render_material(Material *mat)
1046 {
1047         if (mat && mat->nodetree && mat->use_nodes) {
1048                 if (mat->nodetree->execdata)
1049                         ntreeShaderEndExecTree(mat->nodetree->execdata, 1);
1050         }
1051 }
1052
1053 void end_render_materials(Main *bmain)
1054 {
1055         Material *ma;
1056         for (ma = bmain->mat.first; ma; ma = ma->id.next)
1057                 if (ma->id.us) 
1058                         end_render_material(ma);
1059 }
1060
1061 static int material_in_nodetree(bNodeTree *ntree, Material *mat)
1062 {
1063         bNode *node;
1064
1065         for (node = ntree->nodes.first; node; node = node->next) {
1066                 if (node->id) {
1067                         if (GS(node->id->name) == ID_MA) {
1068                                 if (node->id == (ID *)mat) {
1069                                         return 1;
1070                                 }
1071                         }
1072                         else if (node->type == NODE_GROUP) {
1073                                 if (material_in_nodetree((bNodeTree *)node->id, mat)) {
1074                                         return 1;
1075                                 }
1076                         }
1077                 }
1078         }
1079
1080         return 0;
1081 }
1082
1083 int material_in_material(Material *parmat, Material *mat)
1084 {
1085         if (parmat == mat)
1086                 return 1;
1087         else if (parmat->nodetree && parmat->use_nodes)
1088                 return material_in_nodetree(parmat->nodetree, mat);
1089         else
1090                 return 0;
1091 }
1092
1093
1094 /* ****************** */
1095
1096 /* Update drivers for materials in a nodetree */
1097 static void material_node_drivers_update(Scene *scene, bNodeTree *ntree, float ctime)
1098 {
1099         bNode *node;
1100
1101         /* nodetree itself */
1102         if (ntree->adt && ntree->adt->drivers.first) {
1103                 BKE_animsys_evaluate_animdata(scene, &ntree->id, ntree->adt, ctime, ADT_RECALC_DRIVERS);
1104         }
1105         
1106         /* nodes */
1107         for (node = ntree->nodes.first; node; node = node->next) {
1108                 if (node->id) {
1109                         if (GS(node->id->name) == ID_MA) {
1110                                 material_drivers_update(scene, (Material *)node->id, ctime);
1111                         }
1112                         else if (node->type == NODE_GROUP) {
1113                                 material_node_drivers_update(scene, (bNodeTree *)node->id, ctime);
1114                         }
1115                 }
1116         }
1117 }
1118
1119 /* Calculate all drivers for materials 
1120  * FIXME: this is really a terrible method which may result in some things being calculated
1121  * multiple times. However, without proper despgraph support for these things, we are forced
1122  * into this sort of thing...
1123  */
1124 void material_drivers_update(Scene *scene, Material *ma, float ctime)
1125 {
1126         //if (G.f & G_DEBUG)
1127         //      printf("material_drivers_update(%s, %s)\n", scene->id.name, ma->id.name);
1128         
1129         /* Prevent infinite recursion by checking (and tagging the material) as having been visited already
1130          * (see BKE_scene_update_tagged()). This assumes ma->id.flag & LIB_DOIT isn't set by anything else
1131          * in the meantime... [#32017]
1132          */
1133         if (ma->id.flag & LIB_DOIT)
1134                 return;
1135         else
1136                 ma->id.flag |= LIB_DOIT;
1137         
1138         /* material itself */
1139         if (ma->adt && ma->adt->drivers.first) {
1140                 BKE_animsys_evaluate_animdata(scene, &ma->id, ma->adt, ctime, ADT_RECALC_DRIVERS);
1141         }
1142         
1143         /* nodes */
1144         if (ma->nodetree) {
1145                 material_node_drivers_update(scene, ma->nodetree, ctime);
1146         }
1147 }
1148         
1149 /* ****************** */
1150 #if 0 /* UNUSED */
1151 static char colname_array[125][20] = {
1152 "Black", "DarkRed", "HalfRed", "Red", "Red",
1153 "DarkGreen", "DarkOlive", "Brown", "Chocolate", "OrangeRed",
1154 "HalfGreen", "GreenOlive", "DryOlive", "Goldenrod", "DarkOrange",
1155 "LightGreen", "Chartreuse", "YellowGreen", "Yellow", "Gold",
1156 "Green", "LawnGreen", "GreenYellow", "LightOlive", "Yellow",
1157 "DarkBlue", "DarkPurple", "HotPink", "VioletPink", "RedPink",
1158 "SlateGray", "DarkGray", "PalePurple", "IndianRed", "Tomato",
1159 "SeaGreen", "PaleGreen", "GreenKhaki", "LightBrown", "LightSalmon",
1160 "SpringGreen", "PaleGreen", "MediumOlive", "YellowBrown", "LightGold",
1161 "LightGreen", "LightGreen", "LightGreen", "GreenYellow", "PaleYellow",
1162 "HalfBlue", "DarkSky", "HalfMagenta", "VioletRed", "DeepPink",
1163 "SteelBlue", "SkyBlue", "Orchid", "LightHotPink", "HotPink",
1164 "SeaGreen", "SlateGray", "MediumGray", "Burlywood", "LightPink",
1165 "SpringGreen", "Aquamarine", "PaleGreen", "Khaki", "PaleOrange",
1166 "SpringGreen", "SeaGreen", "PaleGreen", "PaleWhite", "YellowWhite",
1167 "LightBlue", "Purple", "MediumOrchid", "Magenta", "Magenta",
1168 "RoyalBlue", "SlateBlue", "MediumOrchid", "Orchid", "Magenta",
1169 "DeepSkyBlue", "LightSteelBlue", "LightSkyBlue", "Violet", "LightPink",
1170 "Cyan", "DarkTurquoise", "SkyBlue", "Gray", "Snow",
1171 "Mint", "Mint", "Aquamarine", "MintCream", "Ivory",
1172 "Blue", "Blue", "DarkMagenta", "DarkOrchid", "Magenta",
1173 "SkyBlue", "RoyalBlue", "LightSlateBlue", "MediumOrchid", "Magenta",
1174 "DodgerBlue", "SteelBlue", "MediumPurple", "PalePurple", "Plum",
1175 "DeepSkyBlue", "PaleBlue", "LightSkyBlue", "PalePurple", "Thistle",
1176 "Cyan", "ColdBlue", "PaleTurquoise", "GhostWhite", "White"
1177 };
1178
1179 void automatname(Material *ma)
1180 {
1181         int nr, r, g, b;
1182         float ref;
1183         
1184         if (ma == NULL) return;
1185         if (ma->mode & MA_SHLESS) ref = 1.0;
1186         else ref = ma->ref;
1187
1188         r = (int)(4.99f * (ref * ma->r));
1189         g = (int)(4.99f * (ref * ma->g));
1190         b = (int)(4.99f * (ref * ma->b));
1191         nr = r + 5 * g + 25 * b;
1192         if (nr > 124) nr = 124;
1193         new_id(&G.main->mat, (ID *)ma, colname_array[nr]);
1194         
1195 }
1196 #endif
1197
1198 int object_remove_material_slot(Object *ob)
1199 {
1200         Material *mao, ***matarar;
1201         Object *obt;
1202         short *totcolp;
1203         short a, actcol;
1204         
1205         if (ob == NULL || ob->totcol == 0) {
1206                 return FALSE;
1207         }
1208
1209         /* this should never happen and used to crash */
1210         if (ob->actcol <= 0) {
1211                 printf("%s: invalid material index %d, report a bug!\n", __func__, ob->actcol);
1212                 BLI_assert(0);
1213                 return FALSE;
1214         }
1215
1216         /* take a mesh/curve/mball as starting point, remove 1 index,
1217          * AND with all objects that share the ob->data
1218          * 
1219          * after that check indices in mesh/curve/mball!!!
1220          */
1221         
1222         totcolp = give_totcolp(ob);
1223         matarar = give_matarar(ob);
1224
1225         if (*matarar == NULL) return FALSE;
1226
1227         /* can happen on face selection in editmode */
1228         if (ob->actcol > ob->totcol) {
1229                 ob->actcol = ob->totcol;
1230         }
1231         
1232         /* we delete the actcol */
1233         mao = (*matarar)[ob->actcol - 1];
1234         if (mao) mao->id.us--;
1235         
1236         for (a = ob->actcol; a < ob->totcol; a++)
1237                 (*matarar)[a - 1] = (*matarar)[a];
1238         (*totcolp)--;
1239         
1240         if (*totcolp == 0) {
1241                 MEM_freeN(*matarar);
1242                 *matarar = NULL;
1243         }
1244         
1245         actcol = ob->actcol;
1246         obt = G.main->object.first;
1247         while (obt) {
1248         
1249                 if (obt->data == ob->data) {
1250                         
1251                         /* WATCH IT: do not use actcol from ob or from obt (can become zero) */
1252                         mao = obt->mat[actcol - 1];
1253                         if (mao) mao->id.us--;
1254                 
1255                         for (a = actcol; a < obt->totcol; a++) {
1256                                 obt->mat[a - 1] = obt->mat[a];
1257                                 obt->matbits[a - 1] = obt->matbits[a];
1258                         }
1259                         obt->totcol--;
1260                         if (obt->actcol > obt->totcol) obt->actcol = obt->totcol;
1261                         
1262                         if (obt->totcol == 0) {
1263                                 MEM_freeN(obt->mat);
1264                                 MEM_freeN(obt->matbits);
1265                                 obt->mat = NULL;
1266                                 obt->matbits = NULL;
1267                         }
1268                 }
1269                 obt = obt->id.next;
1270         }
1271
1272         /* check indices from mesh */
1273         if (ELEM4(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) {
1274                 data_delete_material_index_id((ID *)ob->data, actcol - 1);
1275                 BKE_displist_free(&ob->disp);
1276         }
1277
1278         return TRUE;
1279 }
1280
1281
1282 /* r_col = current value, col = new value, (fac == 0) is no change */
1283 void ramp_blend(int type, float r_col[3], const float fac, const float col[3])
1284 {
1285         float tmp, facm = 1.0f - fac;
1286         
1287         switch (type) {
1288                 case MA_RAMP_BLEND:
1289                         r_col[0] = facm * (r_col[0]) + fac * col[0];
1290                         r_col[1] = facm * (r_col[1]) + fac * col[1];
1291                         r_col[2] = facm * (r_col[2]) + fac * col[2];
1292                         break;
1293                 case MA_RAMP_ADD:
1294                         r_col[0] += fac * col[0];
1295                         r_col[1] += fac * col[1];
1296                         r_col[2] += fac * col[2];
1297                         break;
1298                 case MA_RAMP_MULT:
1299                         r_col[0] *= (facm + fac * col[0]);
1300                         r_col[1] *= (facm + fac * col[1]);
1301                         r_col[2] *= (facm + fac * col[2]);
1302                         break;
1303                 case MA_RAMP_SCREEN:
1304                         r_col[0] = 1.0f - (facm + fac * (1.0f - col[0])) * (1.0f - r_col[0]);
1305                         r_col[1] = 1.0f - (facm + fac * (1.0f - col[1])) * (1.0f - r_col[1]);
1306                         r_col[2] = 1.0f - (facm + fac * (1.0f - col[2])) * (1.0f - r_col[2]);
1307                         break;
1308                 case MA_RAMP_OVERLAY:
1309                         if (r_col[0] < 0.5f)
1310                                 r_col[0] *= (facm + 2.0f * fac * col[0]);
1311                         else
1312                                 r_col[0] = 1.0f - (facm + 2.0f * fac * (1.0f - col[0])) * (1.0f - r_col[0]);
1313                         if (r_col[1] < 0.5f)
1314                                 r_col[1] *= (facm + 2.0f * fac * col[1]);
1315                         else
1316                                 r_col[1] = 1.0f - (facm + 2.0f * fac * (1.0f - col[1])) * (1.0f - r_col[1]);
1317                         if (r_col[2] < 0.5f)
1318                                 r_col[2] *= (facm + 2.0f * fac * col[2]);
1319                         else
1320                                 r_col[2] = 1.0f - (facm + 2.0f * fac * (1.0f - col[2])) * (1.0f - r_col[2]);
1321                         break;
1322                 case MA_RAMP_SUB:
1323                         r_col[0] -= fac * col[0];
1324                         r_col[1] -= fac * col[1];
1325                         r_col[2] -= fac * col[2];
1326                         break;
1327                 case MA_RAMP_DIV:
1328                         if (col[0] != 0.0f)
1329                                 r_col[0] = facm * (r_col[0]) + fac * (r_col[0]) / col[0];
1330                         if (col[1] != 0.0f)
1331                                 r_col[1] = facm * (r_col[1]) + fac * (r_col[1]) / col[1];
1332                         if (col[2] != 0.0f)
1333                                 r_col[2] = facm * (r_col[2]) + fac * (r_col[2]) / col[2];
1334                         break;
1335                 case MA_RAMP_DIFF:
1336                         r_col[0] = facm * (r_col[0]) + fac * fabsf(r_col[0] - col[0]);
1337                         r_col[1] = facm * (r_col[1]) + fac * fabsf(r_col[1] - col[1]);
1338                         r_col[2] = facm * (r_col[2]) + fac * fabsf(r_col[2] - col[2]);
1339                         break;
1340                 case MA_RAMP_DARK:
1341                         tmp = col[0] + ((1 - col[0]) * facm);
1342                         if (tmp < r_col[0]) r_col[0] = tmp;
1343                         tmp = col[1] + ((1 - col[1]) * facm);
1344                         if (tmp < r_col[1]) r_col[1] = tmp;
1345                         tmp = col[2] + ((1 - col[2]) * facm);
1346                         if (tmp < r_col[2]) r_col[2] = tmp;
1347                         break;
1348                 case MA_RAMP_LIGHT:
1349                         tmp = fac * col[0];
1350                         if (tmp > r_col[0]) r_col[0] = tmp;
1351                         tmp = fac * col[1];
1352                         if (tmp > r_col[1]) r_col[1] = tmp;
1353                         tmp = fac * col[2];
1354                         if (tmp > r_col[2]) r_col[2] = tmp;
1355                         break;
1356                 case MA_RAMP_DODGE:
1357                         if (r_col[0] != 0.0f) {
1358                                 tmp = 1.0f - fac * col[0];
1359                                 if (tmp <= 0.0f)
1360                                         r_col[0] = 1.0f;
1361                                 else if ((tmp = (r_col[0]) / tmp) > 1.0f)
1362                                         r_col[0] = 1.0f;
1363                                 else
1364                                         r_col[0] = tmp;
1365                         }
1366                         if (r_col[1] != 0.0f) {
1367                                 tmp = 1.0f - fac * col[1];
1368                                 if (tmp <= 0.0f)
1369                                         r_col[1] = 1.0f;
1370                                 else if ((tmp = (r_col[1]) / tmp) > 1.0f)
1371                                         r_col[1] = 1.0f;
1372                                 else
1373                                         r_col[1] = tmp;
1374                         }
1375                         if (r_col[2] != 0.0f) {
1376                                 tmp = 1.0f - fac * col[2];
1377                                 if (tmp <= 0.0f)
1378                                         r_col[2] = 1.0f;
1379                                 else if ((tmp = (r_col[2]) / tmp) > 1.0f)
1380                                         r_col[2] = 1.0f;
1381                                 else
1382                                         r_col[2] = tmp;
1383                         }
1384                         break;
1385                 case MA_RAMP_BURN:
1386                         tmp = facm + fac * col[0];
1387
1388                         if (tmp <= 0.0f)
1389                                 r_col[0] = 0.0f;
1390                         else if ((tmp = (1.0f - (1.0f - (r_col[0])) / tmp)) < 0.0f)
1391                                 r_col[0] = 0.0f;
1392                         else if (tmp > 1.0f)
1393                                 r_col[0] = 1.0f;
1394                         else
1395                                 r_col[0] = tmp;
1396
1397                         tmp = facm + fac * col[1];
1398                         if (tmp <= 0.0f)
1399                                 r_col[1] = 0.0f;
1400                         else if ((tmp = (1.0f - (1.0f - (r_col[1])) / tmp)) < 0.0f)
1401                                 r_col[1] = 0.0f;
1402                         else if (tmp > 1.0f)
1403                                 r_col[1] = 1.0f;
1404                         else
1405                                 r_col[1] = tmp;
1406
1407                         tmp = facm + fac * col[2];
1408                         if (tmp <= 0.0f)
1409                                 r_col[2] = 0.0f;
1410                         else if ((tmp = (1.0f - (1.0f - (r_col[2])) / tmp)) < 0.0f)
1411                                 r_col[2] = 0.0f;
1412                         else if (tmp > 1.0f)
1413                                 r_col[2] = 1.0f;
1414                         else
1415                                 r_col[2] = tmp;
1416                         break;
1417                 case MA_RAMP_HUE:
1418                 {
1419                         float rH, rS, rV;
1420                         float colH, colS, colV;
1421                         float tmpr, tmpg, tmpb;
1422                         rgb_to_hsv(col[0], col[1], col[2], &colH, &colS, &colV);
1423                         if (colS != 0) {
1424                                 rgb_to_hsv(r_col[0], r_col[1], r_col[2], &rH, &rS, &rV);
1425                                 hsv_to_rgb(colH, rS, rV, &tmpr, &tmpg, &tmpb);
1426                                 r_col[0] = facm * (r_col[0]) + fac * tmpr;
1427                                 r_col[1] = facm * (r_col[1]) + fac * tmpg;
1428                                 r_col[2] = facm * (r_col[2]) + fac * tmpb;
1429                         }
1430                 }
1431                 break;
1432                 case MA_RAMP_SAT:
1433                 {
1434                         float rH, rS, rV;
1435                         float colH, colS, colV;
1436                         rgb_to_hsv(r_col[0], r_col[1], r_col[2], &rH, &rS, &rV);
1437                         if (rS != 0) {
1438                                 rgb_to_hsv(col[0], col[1], col[2], &colH, &colS, &colV);
1439                                 hsv_to_rgb(rH, (facm * rS + fac * colS), rV, r_col + 0, r_col + 1, r_col + 2);
1440                         }
1441                 }
1442                 break;
1443                 case MA_RAMP_VAL:
1444                 {
1445                         float rH, rS, rV;
1446                         float colH, colS, colV;
1447                         rgb_to_hsv(r_col[0], r_col[1], r_col[2], &rH, &rS, &rV);
1448                         rgb_to_hsv(col[0], col[1], col[2], &colH, &colS, &colV);
1449                         hsv_to_rgb(rH, rS, (facm * rV + fac * colV), r_col + 0, r_col + 1, r_col + 2);
1450                 }
1451                 break;
1452                 case MA_RAMP_COLOR:
1453                 {
1454                         float rH, rS, rV;
1455                         float colH, colS, colV;
1456                         float tmpr, tmpg, tmpb;
1457                         rgb_to_hsv(col[0], col[1], col[2], &colH, &colS, &colV);
1458                         if (colS != 0) {
1459                                 rgb_to_hsv(r_col[0], r_col[1], r_col[2], &rH, &rS, &rV);
1460                                 hsv_to_rgb(colH, colS, rV, &tmpr, &tmpg, &tmpb);
1461                                 r_col[0] = facm * (r_col[0]) + fac * tmpr;
1462                                 r_col[1] = facm * (r_col[1]) + fac * tmpg;
1463                                 r_col[2] = facm * (r_col[2]) + fac * tmpb;
1464                         }
1465                 }
1466                 break;
1467                 case MA_RAMP_SOFT:
1468                 {
1469                         float scr, scg, scb;
1470
1471                         /* first calculate non-fac based Screen mix */
1472                         scr = 1.0f - (1.0f - col[0]) * (1.0f - r_col[0]);
1473                         scg = 1.0f - (1.0f - col[1]) * (1.0f - r_col[1]);
1474                         scb = 1.0f - (1.0f - col[2]) * (1.0f - r_col[2]);
1475
1476                         r_col[0] = facm * (r_col[0]) + fac * (((1.0f - r_col[0]) * col[0] * (r_col[0])) + (r_col[0] * scr));
1477                         r_col[1] = facm * (r_col[1]) + fac * (((1.0f - r_col[1]) * col[1] * (r_col[1])) + (r_col[1] * scg));
1478                         r_col[2] = facm * (r_col[2]) + fac * (((1.0f - r_col[2]) * col[2] * (r_col[2])) + (r_col[2] * scb));
1479                 }
1480                 break;
1481                 case MA_RAMP_LINEAR:
1482                         if (col[0] > 0.5f)
1483                                 r_col[0] = r_col[0] + fac * (2.0f * (col[0] - 0.5f));
1484                         else
1485                                 r_col[0] = r_col[0] + fac * (2.0f * (col[0]) - 1.0f);
1486                         if (col[1] > 0.5f)
1487                                 r_col[1] = r_col[1] + fac * (2.0f * (col[1] - 0.5f));
1488                         else
1489                                 r_col[1] = r_col[1] + fac * (2.0f * (col[1]) - 1.0f);
1490                         if (col[2] > 0.5f)
1491                                 r_col[2] = r_col[2] + fac * (2.0f * (col[2] - 0.5f));
1492                         else
1493                                 r_col[2] = r_col[2] + fac * (2.0f * (col[2]) - 1.0f);
1494                         break;
1495         }
1496 }
1497
1498 /**
1499  * \brief copy/paste buffer, if we had a proper py api that would be better
1500  * \note matcopybuf.nodetree does _NOT_ use ID's
1501  * \todo matcopybuf.nodetree's  node->id's are NOT validated, this will crash!
1502  */
1503 static Material matcopybuf;
1504 static short matcopied = 0;
1505
1506 void clear_matcopybuf(void)
1507 {
1508         memset(&matcopybuf, 0, sizeof(Material));
1509         matcopied = 0;
1510 }
1511
1512 void free_matcopybuf(void)
1513 {
1514         int a;
1515
1516         for (a = 0; a < MAX_MTEX; a++) {
1517                 if (matcopybuf.mtex[a]) {
1518                         MEM_freeN(matcopybuf.mtex[a]);
1519                         matcopybuf.mtex[a] = NULL;
1520                 }
1521         }
1522
1523         if (matcopybuf.ramp_col) MEM_freeN(matcopybuf.ramp_col);
1524         if (matcopybuf.ramp_spec) MEM_freeN(matcopybuf.ramp_spec);
1525
1526         matcopybuf.ramp_col = NULL;
1527         matcopybuf.ramp_spec = NULL;
1528
1529         if (matcopybuf.nodetree) {
1530                 ntreeFreeTree_ex(matcopybuf.nodetree, FALSE);
1531                 MEM_freeN(matcopybuf.nodetree);
1532                 matcopybuf.nodetree = NULL;
1533         }
1534
1535         matcopied = 0;
1536 }
1537
1538 void copy_matcopybuf(Material *ma)
1539 {
1540         int a;
1541         MTex *mtex;
1542
1543         if (matcopied)
1544                 free_matcopybuf();
1545
1546         memcpy(&matcopybuf, ma, sizeof(Material));
1547         if (matcopybuf.ramp_col) matcopybuf.ramp_col = MEM_dupallocN(matcopybuf.ramp_col);
1548         if (matcopybuf.ramp_spec) matcopybuf.ramp_spec = MEM_dupallocN(matcopybuf.ramp_spec);
1549
1550         for (a = 0; a < MAX_MTEX; a++) {
1551                 mtex = matcopybuf.mtex[a];
1552                 if (mtex) {
1553                         matcopybuf.mtex[a] = MEM_dupallocN(mtex);
1554                 }
1555         }
1556         matcopybuf.nodetree = ntreeCopyTree_ex(ma->nodetree, FALSE);
1557         matcopybuf.preview = NULL;
1558         matcopybuf.gpumaterial.first = matcopybuf.gpumaterial.last = NULL;
1559         matcopied = 1;
1560 }
1561
1562 void paste_matcopybuf(Material *ma)
1563 {
1564         int a;
1565         MTex *mtex;
1566         ID id;
1567
1568         if (matcopied == 0)
1569                 return;
1570         /* free current mat */
1571         if (ma->ramp_col) MEM_freeN(ma->ramp_col);
1572         if (ma->ramp_spec) MEM_freeN(ma->ramp_spec);
1573         for (a = 0; a < MAX_MTEX; a++) {
1574                 mtex = ma->mtex[a];
1575                 if (mtex && mtex->tex) mtex->tex->id.us--;
1576                 if (mtex) MEM_freeN(mtex);
1577         }
1578
1579         if (ma->nodetree) {
1580                 ntreeFreeTree(ma->nodetree);
1581                 MEM_freeN(ma->nodetree);
1582         }
1583
1584         GPU_material_free(ma);
1585
1586         id = (ma->id);
1587         memcpy(ma, &matcopybuf, sizeof(Material));
1588         (ma->id) = id;
1589
1590         if (matcopybuf.ramp_col) ma->ramp_col = MEM_dupallocN(matcopybuf.ramp_col);
1591         if (matcopybuf.ramp_spec) ma->ramp_spec = MEM_dupallocN(matcopybuf.ramp_spec);
1592
1593         for (a = 0; a < MAX_MTEX; a++) {
1594                 mtex = ma->mtex[a];
1595                 if (mtex) {
1596                         ma->mtex[a] = MEM_dupallocN(mtex);
1597                         if (mtex->tex) id_us_plus((ID *)mtex->tex);
1598                 }
1599         }
1600
1601         ma->nodetree = ntreeCopyTree_ex(matcopybuf.nodetree, FALSE);
1602 }
1603
1604
1605 /*********************** texface to material convert functions **********************/
1606 /* encode all the TF information into a single int */
1607 static int encode_tfaceflag(MTFace *tf, int convertall)
1608 {
1609         /* calculate the flag */
1610         int flag = tf->mode;
1611
1612         /* options that change the material offline render */
1613         if (!convertall) {
1614                 flag &= ~TF_OBCOL;
1615         }
1616
1617         /* clean flags that are not being converted */
1618         flag &= ~TF_TEX;
1619         flag &= ~TF_SHAREDVERT;
1620         flag &= ~TF_SHAREDCOL;
1621         flag &= ~TF_CONVERTED;
1622
1623         /* light tface flag is ignored in GLSL mode */
1624         flag &= ~TF_LIGHT;
1625         
1626         /* 15 is how big the flag can be - hardcoded here and in decode_tfaceflag() */
1627         flag |= tf->transp << 15;
1628         
1629         /* increase 1 so flag 0 is different than no flag yet */
1630         return flag + 1;
1631 }
1632
1633 /* set the material options based in the tface flag */
1634 static void decode_tfaceflag(Material *ma, int flag, int convertall)
1635 {
1636         int alphablend;
1637         GameSettings *game = &ma->game;
1638
1639         /* flag is shifted in 1 to make 0 != no flag yet (see encode_tfaceflag) */
1640         flag -= 1;
1641
1642         alphablend = flag >> 15;  /* encoded in the encode_tfaceflag function */
1643         (*game).flag = 0;
1644         
1645         /* General Material Options */
1646         if ((flag & TF_DYNAMIC) == 0) (*game).flag    |= GEMAT_NOPHYSICS;
1647         
1648         /* Material Offline Rendering Properties */
1649         if (convertall) {
1650                 if (flag & TF_OBCOL) ma->shade_flag |= MA_OBCOLOR;
1651         }
1652         
1653         /* Special Face Properties */
1654         if ((flag & TF_TWOSIDE) == 0) (*game).flag |= GEMAT_BACKCULL;
1655         if (flag & TF_INVISIBLE) (*game).flag |= GEMAT_INVISIBLE;
1656         if (flag & TF_BMFONT) (*game).flag |= GEMAT_TEXT;
1657         
1658         /* Face Orientation */
1659         if (flag & TF_BILLBOARD) (*game).face_orientation |= GEMAT_HALO;
1660         else if (flag & TF_BILLBOARD2) (*game).face_orientation |= GEMAT_BILLBOARD;
1661         else if (flag & TF_SHADOW) (*game).face_orientation |= GEMAT_SHADOW;
1662         
1663         /* Alpha Blend */
1664         if (flag & TF_ALPHASORT && ELEM(alphablend, TF_ALPHA, TF_ADD)) (*game).alpha_blend = GEMAT_ALPHA_SORT;
1665         else if (alphablend & TF_ALPHA) (*game).alpha_blend = GEMAT_ALPHA;
1666         else if (alphablend & TF_ADD) (*game).alpha_blend = GEMAT_ADD;
1667         else if (alphablend & TF_CLIP) (*game).alpha_blend = GEMAT_CLIP;
1668 }
1669
1670 /* boolean check to see if the mesh needs a material */
1671 static int check_tfaceneedmaterial(int flag)
1672 {
1673         /* check if the flags we have are not deprecated != than default material options
1674          * also if only flags are visible and collision see if all objects using this mesh have this option in physics */
1675
1676         /* flag is shifted in 1 to make 0 != no flag yet (see encode_tfaceflag) */
1677         flag -= 1;
1678
1679         /* deprecated flags */
1680         flag &= ~TF_OBCOL;
1681         flag &= ~TF_SHAREDVERT;
1682         flag &= ~TF_SHAREDCOL;
1683
1684         /* light tface flag is ignored in GLSL mode */
1685         flag &= ~TF_LIGHT;
1686         
1687         /* automatic detected if tex image has alpha */
1688         flag &= ~(TF_ALPHA << 15);
1689         /* automatic detected if using texture */
1690         flag &= ~TF_TEX;
1691
1692         /* settings for the default NoMaterial */
1693         if (flag == TF_DYNAMIC)
1694                 return 0;
1695
1696         else
1697                 return 1;
1698 }
1699
1700 /* return number of digits of an integer */
1701 /* XXX to be optmized or replaced by an equivalent blender internal function */
1702 static int integer_getdigits(int number)
1703 {
1704         int i = 0;
1705         if (number == 0) return 1;
1706
1707         while (number != 0) {
1708                 number = (int)(number / 10);
1709                 i++;
1710         }
1711         return i;
1712 }
1713
1714 static void calculate_tface_materialname(char *matname, char *newname, int flag)
1715 {
1716         /* if flag has only light and collision and material matches those values
1717          * you can do strcpy(name, mat_name);
1718          * otherwise do: */
1719         int digits = integer_getdigits(flag);
1720         /* clamp the old name, remove the MA prefix and add the .TF.flag suffix
1721          * e.g. matname = "MALoooooooooooooongName"; newname = "Loooooooooooooon.TF.2" */
1722         BLI_snprintf(newname, MAX_ID_NAME, "%.*s.TF.%0*d", MAX_ID_NAME - (digits + 5), matname, digits, flag);
1723 }
1724
1725 /* returns -1 if no match */
1726 static short mesh_getmaterialnumber(Mesh *me, Material *ma)
1727 {
1728         short a;
1729
1730         for (a = 0; a < me->totcol; a++) {
1731                 if (me->mat[a] == ma) {
1732                         return a;
1733                 }
1734         }
1735
1736         return -1;
1737 }
1738
1739 /* append material */
1740 static short mesh_addmaterial(Mesh *me, Material *ma)
1741 {
1742         material_append_id(&me->id, NULL);
1743         me->mat[me->totcol - 1] = ma;
1744
1745         id_us_plus(&ma->id);
1746
1747         return me->totcol - 1;
1748 }
1749
1750 static void set_facetexture_flags(Material *ma, Image *image)
1751 {
1752         if (image) {
1753                 ma->mode |= MA_FACETEXTURE;
1754                 /* we could check if the texture has alpha, but then more meshes sharing the same
1755                  * material may need it. Let's make it simple. */
1756                 if (BKE_image_has_alpha(image))
1757                         ma->mode |= MA_FACETEXTURE_ALPHA;
1758         }
1759 }
1760
1761 /* returns material number */
1762 static short convert_tfacenomaterial(Main *main, Mesh *me, MTFace *tf, int flag)
1763 {
1764         Material *ma;
1765         char idname[MAX_ID_NAME];
1766         short mat_nr = -1;
1767         
1768         /* new material, the name uses the flag*/
1769         BLI_snprintf(idname, sizeof(idname), "MAMaterial.TF.%0*d", integer_getdigits(flag), flag);
1770
1771         if ((ma = BLI_findstring(&main->mat, idname + 2, offsetof(ID, name) + 2))) {
1772                 mat_nr = mesh_getmaterialnumber(me, ma);
1773                 /* assign the material to the mesh */
1774                 if (mat_nr == -1) mat_nr = mesh_addmaterial(me, ma);
1775
1776                 /* if needed set "Face Textures [Alpha]" Material options */
1777                 set_facetexture_flags(ma, tf->tpage);
1778         }
1779         /* create a new material */
1780         else {
1781                 ma = BKE_material_add(idname + 2);
1782
1783                 if (ma) {
1784                         printf("TexFace Convert: Material \"%s\" created.\n", idname + 2);
1785                         mat_nr = mesh_addmaterial(me, ma);
1786                         
1787                         /* if needed set "Face Textures [Alpha]" Material options */
1788                         set_facetexture_flags(ma, tf->tpage);
1789
1790                         decode_tfaceflag(ma, flag, 1);
1791                         /* the final decoding will happen after, outside the main loop
1792                          * for now store the flag into the material and change light/tex/collision
1793                          * store the flag as a negative number */
1794                         ma->game.flag = -flag;
1795                         id_us_min((ID *)ma);
1796                 }
1797                 else printf("Error: Unable to create Material \"%s\" for Mesh \"%s\".", idname + 2, me->id.name + 2);
1798         }
1799
1800         /* set as converted, no need to go bad to this face */
1801         tf->mode |= TF_CONVERTED;
1802         return mat_nr;
1803 }
1804
1805 /* Function to fully convert materials */
1806 static void convert_tfacematerial(Main *main, Material *ma)
1807 {
1808         Mesh *me;
1809         Material *mat_new;
1810         MFace *mf;
1811         MTFace *tf;
1812         int flag, index;
1813         int a;
1814         short mat_nr;
1815         CustomDataLayer *cdl;
1816         char idname[MAX_ID_NAME];
1817
1818         for (me = main->mesh.first; me; me = me->id.next) {
1819                 /* check if this mesh uses this material */
1820                 for (a = 0; a < me->totcol; a++)
1821                         if (me->mat[a] == ma) break;
1822                         
1823                 /* no material found */
1824                 if (a == me->totcol) continue;
1825
1826                 /* get the active tface layer */
1827                 index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
1828                 cdl = (index == -1) ? NULL : &me->fdata.layers[index];
1829                 if (!cdl) continue;
1830
1831                 /* loop over all the faces and stop at the ones that use the material*/
1832                 for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
1833                         if (me->mat[mf->mat_nr] != ma) continue;
1834
1835                         /* texface data for this face */
1836                         tf = ((MTFace *)cdl->data) + a;
1837                         flag = encode_tfaceflag(tf, 1);
1838
1839                         /* the name of the new material */
1840                         calculate_tface_materialname(ma->id.name, (char *)&idname, flag);
1841
1842                         if ((mat_new = BLI_findstring(&main->mat, idname + 2, offsetof(ID, name) + 2))) {
1843                                 /* material already existent, see if the mesh has it */
1844                                 mat_nr = mesh_getmaterialnumber(me, mat_new);
1845                                 /* material is not in the mesh, add it */
1846                                 if (mat_nr == -1) mat_nr = mesh_addmaterial(me, mat_new);
1847                         }
1848                         /* create a new material */
1849                         else {
1850                                 mat_new = BKE_material_copy(ma);
1851                                 if (mat_new) {
1852                                         /* rename the material*/
1853                                         BLI_strncpy(mat_new->id.name, idname, sizeof(mat_new->id.name));
1854                                         id_us_min((ID *)mat_new);
1855
1856                                         mat_nr = mesh_addmaterial(me, mat_new);
1857                                         decode_tfaceflag(mat_new, flag, 1);
1858                                 }
1859                                 else {
1860                                         printf("Error: Unable to create Material \"%s\" for Mesh \"%s.", idname + 2, me->id.name + 2);
1861                                         mat_nr = mf->mat_nr;
1862                                         continue;
1863                                 }
1864                         }
1865                         
1866                         /* if the material has a texture but no texture channel
1867                          * set "Face Textures [Alpha]" Material options 
1868                          * actually we need to run it always, because of old behavior
1869                          * of using face texture if any texture channel was present (multitex) */
1870                         //if ((!mat_new->mtex[0]) && (!mat_new->mtex[0]->tex))
1871                         set_facetexture_flags(mat_new, tf->tpage);
1872
1873                         /* set the material number to the face*/
1874                         mf->mat_nr = mat_nr;
1875                 }
1876                 /* remove material from mesh */
1877                 for (a = 0; a < me->totcol; )
1878                         if (me->mat[a] == ma) material_pop_id(&me->id, a, 1); else a++;
1879         }
1880 }
1881
1882
1883 #define MAT_BGE_DISPUTED -99999
1884
1885 int do_version_tface(Main *main, int fileload)
1886 {
1887         Mesh *me;
1888         Material *ma;
1889         MFace *mf;
1890         MTFace *tf;
1891         CustomDataLayer *cdl;
1892         int a;
1893         int flag;
1894         int index;
1895
1896         /* sometimes mesh has no materials but will need a new one. In those
1897          * cases we need to ignore the mf->mat_nr and only look at the face
1898          * mode because it can be zero as uninitialized or the 1st created material
1899          */
1900         int nomaterialslots;
1901
1902         /* alert to user to check the console */
1903         int nowarning = 1;
1904
1905         /* mark all the materials to conversion with a flag
1906          * if there is tface create a complete flag for that storing in flag
1907          * if there is tface and flag > 0: creates a new flag based on this face
1908          * if flags are different set flag to -1  
1909          */
1910         
1911         /* 1st part: marking mesh materials to update */
1912         for (me = main->mesh.first; me; me = me->id.next) {
1913                 if (me->id.lib) continue;
1914
1915                 /* get the active tface layer */
1916                 index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
1917                 cdl = (index == -1) ? NULL : &me->fdata.layers[index];
1918                 if (!cdl) continue;
1919
1920                 nomaterialslots = (me->totcol == 0 ? 1 : 0);
1921                 
1922                 /* loop over all the faces*/
1923                 for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
1924                         /* texface data for this face */
1925                         tf = ((MTFace *)cdl->data) + a;
1926
1927                         /* conversion should happen only once */
1928                         if (fileload)
1929                                 tf->mode &= ~TF_CONVERTED;
1930                         else {
1931                                 if ((tf->mode & TF_CONVERTED)) continue;
1932                                 else tf->mode |= TF_CONVERTED;
1933                         }
1934                         
1935                         /* no material slots */
1936                         if (nomaterialslots) {
1937                                 flag = encode_tfaceflag(tf, 1);
1938                                 
1939                                 /* create/find a new material and assign to the face */
1940                                 if (check_tfaceneedmaterial(flag)) {
1941                                         mf->mat_nr = convert_tfacenomaterial(main, me, tf, flag);
1942                                 }
1943                                 /* else mark them as no-material to be reverted to 0 later */
1944                                 else {
1945                                         mf->mat_nr = -1;
1946                                 }
1947                         }
1948                         else if (mf->mat_nr < me->totcol) {
1949                                 ma = me->mat[mf->mat_nr];
1950                                 
1951                                 /* no material create one if necessary */
1952                                 if (!ma) {
1953                                         /* find a new material and assign to the face */
1954                                         flag = encode_tfaceflag(tf, 1);
1955
1956                                         /* create/find a new material and assign to the face */
1957                                         if (check_tfaceneedmaterial(flag))
1958                                                 mf->mat_nr = convert_tfacenomaterial(main, me, tf, flag);
1959
1960                                         continue;
1961                                 }
1962
1963                                 /* we can't read from this if it comes from a library,
1964                                  * at doversion time: direct_link might not have happened on it,
1965                                  * so ma->mtex is not pointing to valid memory yet.
1966                                  * later we could, but it's better not */
1967                                 else if (ma->id.lib)
1968                                         continue;
1969                                 
1970                                 /* material already marked as disputed */
1971                                 else if (ma->game.flag == MAT_BGE_DISPUTED)
1972                                         continue;
1973
1974                                 /* found a material */
1975                                 else {
1976                                         flag = encode_tfaceflag(tf, ((fileload) ? 0 : 1));
1977
1978                                         /* first time changing this material */
1979                                         if (ma->game.flag == 0)
1980                                                 ma->game.flag = -flag;
1981                         
1982                                         /* mark material as disputed */
1983                                         else if (ma->game.flag != -flag) {
1984                                                 ma->game.flag = MAT_BGE_DISPUTED;
1985                                                 continue;
1986                                         }
1987                         
1988                                         /* material ok so far */
1989                                         else {
1990                                                 ma->game.flag = -flag;
1991                                                 
1992                                                 /* some people uses multitexture with TexFace by creating a texture
1993                                                  * channel which not necessarily the tf->tpage image. But the game engine
1994                                                  * was enabling it. Now it's required to set "Face Texture [Alpha] in the
1995                                                  * material settings. */
1996                                                 if (!fileload)
1997                                                         set_facetexture_flags(ma, tf->tpage);
1998                                         }
1999                                 }
2000                         }
2001                         else {
2002                                 continue;
2003                         }
2004                 }
2005
2006                 /* if we didn't have material slot and now we do, we need to
2007                  * make sure the materials are correct */
2008                 if (nomaterialslots) {
2009                         if (me->totcol > 0) {
2010                                 for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
2011                                         if (mf->mat_nr == -1) {
2012                                                 /* texface data for this face */
2013                                                 tf = ((MTFace *)cdl->data) + a;
2014                                                 mf->mat_nr = convert_tfacenomaterial(main, me, tf, encode_tfaceflag(tf, 1));
2015                                         }
2016                                 }
2017                         }
2018                         else {
2019                                 for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
2020                                         mf->mat_nr = 0;
2021                                 }
2022                         }
2023                 }
2024
2025         }
2026         
2027         /* 2nd part - conversion */
2028         /* skip library files */
2029
2030         /* we shouldn't loop through the materials created in the loop. make the loop stop at its original length) */
2031         for (ma = main->mat.first, a = 0; ma; ma = ma->id.next, a++) {
2032                 if (ma->id.lib) continue;
2033
2034                 /* disputed material */
2035                 if (ma->game.flag == MAT_BGE_DISPUTED) {
2036                         ma->game.flag = 0;
2037                         if (fileload) {
2038                                 printf("Warning: material \"%s\" skipped - to convert old game texface to material go to the Help menu.\n", ma->id.name + 2);
2039                                 nowarning = 0;
2040                         }
2041                         else
2042                                 convert_tfacematerial(main, ma); continue;
2043                 }
2044         
2045                 /* no conflicts in this material - 90% of cases
2046                  * convert from tface system to material */
2047                 else if (ma->game.flag < 0) {
2048                         decode_tfaceflag(ma, -(ma->game.flag), 1);
2049
2050                         /* material is good make sure all faces using
2051                          * this material are set to converted */
2052                         if (fileload) {
2053                                 for (me = main->mesh.first; me; me = me->id.next) {
2054                                         /* check if this mesh uses this material */
2055                                         for (a = 0; a < me->totcol; a++)
2056                                                 if (me->mat[a] == ma) break;
2057                                                 
2058                                         /* no material found */
2059                                         if (a == me->totcol) continue;
2060                         
2061                                         /* get the active tface layer */
2062                                         index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
2063                                         cdl = (index == -1) ? NULL : &me->fdata.layers[index];
2064                                         if (!cdl) continue;
2065                         
2066                                         /* loop over all the faces and stop at the ones that use the material*/
2067                                         for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
2068                                                 if (me->mat[mf->mat_nr] == ma) {
2069                                                         /* texface data for this face */
2070                                                         tf = ((MTFace *)cdl->data) + a;
2071                                                         tf->mode |= TF_CONVERTED;
2072                                                 }
2073                                         }
2074                                 }
2075                         }
2076                 }
2077                 /* material is not used by faces with texface
2078                  * set the default flag - do it only once */
2079                 else {
2080                         if (fileload) {
2081                                 ma->game.flag = GEMAT_BACKCULL;
2082                         }
2083                 }
2084         }
2085
2086         return nowarning;
2087 }
2088