2 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
18 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19 * All rights reserved.
21 * The Original Code is: all of this file.
23 * Contributor(s): none yet.
25 * ***** END GPL LICENSE BLOCK *****
28 /** \file blender/blenkernel/intern/material.c
37 #include "MEM_guardedalloc.h"
39 #include "DNA_anim_types.h"
40 #include "DNA_curve_types.h"
41 #include "DNA_material_types.h"
42 #include "DNA_mesh_types.h"
43 #include "DNA_meshdata_types.h"
44 #include "DNA_customdata_types.h"
46 #include "DNA_meta_types.h"
47 #include "DNA_node_types.h"
48 #include "DNA_object_types.h"
49 #include "DNA_scene_types.h"
52 #include "BLI_listbase.h"
53 #include "BLI_utildefines.h"
54 #include "BLI_bpath.h"
55 #include "BLI_string.h"
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"
64 #include "BKE_material.h"
67 #include "BKE_curve.h"
69 #include "GPU_material.h"
71 /* used in UI and render */
74 /* called on startup, creator.c */
75 void init_def_material(void)
77 init_material(&defmaterial);
80 /* not material itself */
81 void BKE_material_free(Material *ma)
86 for (a = 0; a < MAX_MTEX; a++) {
88 if (mtex && mtex->tex) mtex->tex->id.us--;
89 if (mtex) MEM_freeN(mtex);
92 if (ma->ramp_col) MEM_freeN(ma->ramp_col);
93 if (ma->ramp_spec) MEM_freeN(ma->ramp_spec);
95 BKE_free_animdata((ID *)ma);
98 BKE_previewimg_free(&ma->preview);
99 BKE_icon_delete((struct ID *)ma);
102 /* is no lib link block, but material extension */
104 ntreeFreeTree(ma->nodetree);
105 MEM_freeN(ma->nodetree);
108 if (ma->gpumaterial.first)
109 GPU_material_free(ma);
112 void init_material(Material *ma)
114 ma->r = ma->g = ma->b = ma->ref = 0.8;
115 ma->specr = ma->specg = ma->specb = 1.0;
116 ma->mirr = ma->mirg = ma->mirb = 1.0;
120 ma->spec = ma->hasize = 0.5;
122 ma->starc = ma->ringc = 4;
125 ma->flaresize = ma->subsize = 1.0;
138 ma->strand_sta = ma->strand_end = 1.0f;
142 ma->ray_depth_tra = 2;
143 ma->fresnel_mir = 0.0;
144 ma->fresnel_tra = 0.0;
145 ma->fresnel_tra_i = 1.25;
146 ma->fresnel_mir_i = 1.25;
148 ma->tx_falloff = 1.0;
149 ma->shad_alpha = 1.0f;
151 ma->gloss_mir = ma->gloss_tra = 1.0;
152 ma->samp_gloss_mir = ma->samp_gloss_tra = 18;
153 ma->adapt_thresh_mir = ma->adapt_thresh_tra = 0.005;
155 ma->fadeto_mir = MA_RAYMIR_FADETOSKY;
157 ma->rampfac_col = 1.0;
158 ma->rampfac_spec = 1.0;
159 ma->pr_lamp = 3; /* two lamps, is bits */
160 ma->pr_type = MA_SPHERE;
162 ma->sss_radius[0] = 1.0f;
163 ma->sss_radius[1] = 1.0f;
164 ma->sss_radius[2] = 1.0f;
165 ma->sss_col[0] = 1.0f;
166 ma->sss_col[1] = 1.0f;
167 ma->sss_col[2] = 1.0f;
168 ma->sss_error = 0.05f;
169 ma->sss_scale = 0.1f;
171 ma->sss_colfac = 1.0f;
172 ma->sss_texfac = 0.0f;
173 ma->sss_front = 1.0f;
176 ma->vol.density = 1.0f;
177 ma->vol.emission = 0.0f;
178 ma->vol.scattering = 1.0f;
179 ma->vol.reflection = 1.0f;
180 ma->vol.transmission_col[0] = ma->vol.transmission_col[1] = ma->vol.transmission_col[2] = 1.0f;
181 ma->vol.reflection_col[0] = ma->vol.reflection_col[1] = ma->vol.reflection_col[2] = 1.0f;
182 ma->vol.emission_col[0] = ma->vol.emission_col[1] = ma->vol.emission_col[2] = 1.0f;
183 ma->vol.density_scale = 1.0f;
184 ma->vol.depth_cutoff = 0.01f;
185 ma->vol.stepsize_type = MA_VOL_STEP_RANDOMIZED;
186 ma->vol.stepsize = 0.2f;
187 ma->vol.shade_type = MA_VOL_SHADE_SHADED;
188 ma->vol.shadeflag |= MA_VOL_PRECACHESHADING;
189 ma->vol.precache_resolution = 50;
190 ma->vol.ms_spread = 0.2f;
191 ma->vol.ms_diff = 1.f;
192 ma->vol.ms_intensity = 1.f;
194 ma->game.flag = GEMAT_BACKCULL;
195 ma->game.alpha_blend = 0;
196 ma->game.face_orientation = 0;
198 ma->mode = MA_TRACEBLE | MA_SHADBUF | MA_SHADOW | MA_RAYBIAS | MA_TANGENT_STR | MA_ZTRANSP;
199 ma->shade_flag = MA_APPROX_OCCLUSION;
203 Material *BKE_material_add(const char *name)
207 ma = BKE_libblock_alloc(&G.main->mat, ID_MA, name);
214 /* XXX keep synced with next function */
215 Material *BKE_material_copy(Material *ma)
220 man = BKE_libblock_copy(&ma->id);
222 id_lib_extern((ID *)man->group);
224 for (a = 0; a < MAX_MTEX; a++) {
226 man->mtex[a] = MEM_mallocN(sizeof(MTex), "copymaterial");
227 memcpy(man->mtex[a], ma->mtex[a], sizeof(MTex));
228 id_us_plus((ID *)man->mtex[a]->tex);
232 if (ma->ramp_col) man->ramp_col = MEM_dupallocN(ma->ramp_col);
233 if (ma->ramp_spec) man->ramp_spec = MEM_dupallocN(ma->ramp_spec);
235 if (ma->preview) man->preview = BKE_previewimg_copy(ma->preview);
238 man->nodetree = ntreeCopyTree(ma->nodetree); /* 0 == full new tree */
241 man->gpumaterial.first = man->gpumaterial.last = NULL;
246 /* XXX (see above) material copy without adding to main dbase */
247 Material *localize_material(Material *ma)
252 man = BKE_libblock_copy(&ma->id);
253 BLI_remlink(&G.main->mat, man);
255 /* no increment for texture ID users, in previewrender.c it prevents decrement */
256 for (a = 0; a < MAX_MTEX; a++) {
258 man->mtex[a] = MEM_mallocN(sizeof(MTex), "copymaterial");
259 memcpy(man->mtex[a], ma->mtex[a], sizeof(MTex));
263 if (ma->ramp_col) man->ramp_col = MEM_dupallocN(ma->ramp_col);
264 if (ma->ramp_spec) man->ramp_spec = MEM_dupallocN(ma->ramp_spec);
269 man->nodetree = ntreeLocalize(ma->nodetree);
271 man->gpumaterial.first = man->gpumaterial.last = NULL;
276 static void extern_local_material(Material *ma)
279 for (i = 0; i < MAX_MTEX; i++) {
280 if (ma->mtex[i]) id_lib_extern((ID *)ma->mtex[i]->tex);
284 void BKE_material_make_local(Material *ma)
286 Main *bmain = G.main;
291 int a, is_local = FALSE, is_lib = FALSE;
293 /* - only lib users: do nothing
294 * - only local users: set flag
298 if (ma->id.lib == NULL) return;
300 /* One local user; set flag and return. */
301 if (ma->id.us == 1) {
302 id_clear_lib_data(bmain, &ma->id);
303 extern_local_material(ma);
307 /* Check which other IDs reference this one to determine if it's used by
310 ob = bmain->object.first;
313 for (a = 0; a < ob->totcol; a++) {
314 if (ob->mat[a] == ma) {
315 if (ob->id.lib) is_lib = TRUE;
316 else is_local = TRUE;
323 me = bmain->mesh.first;
326 for (a = 0; a < me->totcol; a++) {
327 if (me->mat[a] == ma) {
328 if (me->id.lib) is_lib = TRUE;
329 else is_local = TRUE;
336 cu = bmain->curve.first;
339 for (a = 0; a < cu->totcol; a++) {
340 if (cu->mat[a] == ma) {
341 if (cu->id.lib) is_lib = TRUE;
342 else is_local = TRUE;
349 mb = bmain->mball.first;
352 for (a = 0; a < mb->totcol; a++) {
353 if (mb->mat[a] == ma) {
354 if (mb->id.lib) is_lib = TRUE;
355 else is_local = TRUE;
362 /* Only local users. */
363 if (is_local && is_lib == FALSE) {
364 id_clear_lib_data(bmain, &ma->id);
365 extern_local_material(ma);
367 /* Both user and local, so copy. */
368 else if (is_local && is_lib) {
369 Material *ma_new = BKE_material_copy(ma);
373 /* Remap paths of new ID using old library as base. */
374 BKE_id_lib_local_paths(bmain, ma->id.lib, &ma_new->id);
377 ob = bmain->object.first;
380 for (a = 0; a < ob->totcol; a++) {
381 if (ob->mat[a] == ma) {
382 if (ob->id.lib == NULL) {
393 me = bmain->mesh.first;
396 for (a = 0; a < me->totcol; a++) {
397 if (me->mat[a] == ma) {
398 if (me->id.lib == NULL) {
409 cu = bmain->curve.first;
412 for (a = 0; a < cu->totcol; a++) {
413 if (cu->mat[a] == ma) {
414 if (cu->id.lib == NULL) {
425 mb = bmain->mball.first;
428 for (a = 0; a < mb->totcol; a++) {
429 if (mb->mat[a] == ma) {
430 if (mb->id.lib == NULL) {
443 /* for curve, mball, mesh types */
444 void extern_local_matarar(struct Material **matar, short totcol)
447 for (i = 0; i < totcol; i++) {
448 id_lib_extern((ID *)matar[i]);
452 Material ***give_matarar(Object *ob)
458 if (ob->type == OB_MESH) {
462 else if (ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
466 else if (ob->type == OB_MBALL) {
473 short *give_totcolp(Object *ob)
479 if (ob->type == OB_MESH) {
481 return &(me->totcol);
483 else if (ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
485 return &(cu->totcol);
487 else if (ob->type == OB_MBALL) {
489 return &(mb->totcol);
494 /* same as above but for ID's */
495 Material ***give_matarar_id(ID *id)
497 switch (GS(id->name)) {
499 return &(((Mesh *)id)->mat);
502 return &(((Curve *)id)->mat);
505 return &(((MetaBall *)id)->mat);
511 short *give_totcolp_id(ID *id)
513 switch (GS(id->name)) {
515 return &(((Mesh *)id)->totcol);
518 return &(((Curve *)id)->totcol);
521 return &(((MetaBall *)id)->totcol);
527 static void data_delete_material_index_id(ID *id, short index)
529 switch (GS(id->name)) {
531 BKE_mesh_delete_material_index((Mesh *)id, index);
534 BKE_curve_delete_material_index((Curve *)id, index);
537 /* meta-elems don't have materials atm */
542 void material_append_id(ID *id, Material *ma)
545 if ((matar = give_matarar_id(id))) {
546 short *totcol = give_totcolp_id(id);
547 Material **mat = MEM_callocN(sizeof(void *) * ((*totcol) + 1), "newmatar");
548 if (*totcol) memcpy(mat, *matar, sizeof(void *) * (*totcol));
549 if (*matar) MEM_freeN(*matar);
552 (*matar)[(*totcol)++] = ma;
554 id_us_plus((ID *)ma);
555 test_object_materials(id);
559 Material *material_pop_id(ID *id, int index_i, int remove_material_slot)
561 short index = (short)index_i;
562 Material *ret = NULL;
564 if ((matar = give_matarar_id(id))) {
565 short *totcol = give_totcolp_id(id);
566 if (index >= 0 && index < (*totcol)) {
567 ret = (*matar)[index];
568 id_us_min((ID *)ret);
570 if (remove_material_slot) {
578 if (index + 1 != (*totcol))
579 memmove((*matar) + index, (*matar) + (index + 1), sizeof(void *) * ((*totcol) - (index + 1)));
583 mat = MEM_callocN(sizeof(void *) * (*totcol), "newmatar");
584 memcpy(mat, *matar, sizeof(void *) * (*totcol));
588 test_object_materials(id);
591 /* decrease mat_nr index */
592 data_delete_material_index_id(id, index);
595 /* don't remove material slot, only clear it*/
597 (*matar)[index] = NULL;
604 Material *give_current_material(Object *ob, short act)
606 Material ***matarar, *ma;
609 if (ob == NULL) return NULL;
611 /* if object cannot have material, (totcolp == NULL) */
612 totcolp = give_totcolp(ob);
613 if (totcolp == NULL || ob->totcol == 0) return NULL;
619 if (act > ob->totcol) act = ob->totcol;
620 else if (act <= 0) act = 1;
622 if (ob->matbits && ob->matbits[act - 1]) { /* in object */
623 ma = ob->mat[act - 1];
627 /* check for inconsistency */
628 if (*totcolp < ob->totcol)
629 ob->totcol = *totcolp;
630 if (act > ob->totcol) act = ob->totcol;
632 matarar = give_matarar(ob);
634 if (matarar && *matarar) ma = (*matarar)[act - 1];
642 ID *material_from(Object *ob, short act)
645 if (ob == NULL) return NULL;
647 if (ob->totcol == 0) return ob->data;
648 if (act == 0) act = 1;
650 if (ob->matbits[act - 1]) return (ID *)ob;
651 else return ob->data;
654 Material *give_node_material(Material *ma)
656 if (ma && ma->use_nodes && ma->nodetree) {
657 bNode *node = nodeGetActiveID(ma->nodetree, ID_MA);
660 return (Material *)node->id;
666 /* GS reads the memory pointed at in a specific ordering. There are,
667 * however two definitions for it. I have jotted them down here, both,
668 * but I think the first one is actually used. The thing is that
669 * big-endian systems might read this the wrong way round. OTOH, we
670 * constructed the IDs that are read out with this macro explicitly as
671 * well. I expect we'll sort it out soon... */
674 #define GS(a) (*((short *)(a)))
676 /* from misc_util: flip the bytes from x */
677 /* #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */
679 void resize_object_material(Object *ob, const short totcol)
687 MEM_freeN(ob->matbits);
692 else if (ob->totcol < totcol) {
693 newmatar = MEM_callocN(sizeof(void *) * totcol, "newmatar");
694 newmatbits = MEM_callocN(sizeof(char) * totcol, "newmatbits");
696 memcpy(newmatar, ob->mat, sizeof(void *) * ob->totcol);
697 memcpy(newmatbits, ob->matbits, sizeof(char) * ob->totcol);
699 MEM_freeN(ob->matbits);
702 ob->matbits = newmatbits;
705 if (ob->totcol && ob->actcol == 0) ob->actcol = 1;
706 if (ob->actcol > ob->totcol) ob->actcol = ob->totcol;
709 void test_object_materials(ID *id)
711 /* make the ob mat-array same size as 'ob->data' mat-array */
715 if (id == NULL || (totcol = give_totcolp_id(id)) == NULL) {
719 for (ob = G.main->object.first; ob; ob = ob->id.next) {
720 if (ob->data == id) {
721 resize_object_material(ob, *totcol);
726 void assign_material_id(ID *id, Material *ma, short act)
728 Material *mao, **matar, ***matarar;
731 if (act > MAXMAT) return;
732 if (act < 1) act = 1;
734 /* prevent crashing when using accidentally */
735 BLI_assert(id->lib == NULL);
740 totcolp = give_totcolp_id(id);
741 matarar = give_matarar_id(id);
743 if (totcolp == NULL || matarar == NULL) return;
745 if (act > *totcolp) {
746 matar = MEM_callocN(sizeof(void *) * act, "matarray1");
749 memcpy(matar, *matarar, sizeof(void *) * (*totcolp));
758 mao = (*matarar)[act - 1];
759 if (mao) mao->id.us--;
760 (*matarar)[act - 1] = ma;
763 id_us_plus((ID *)ma);
765 test_object_materials(id);
768 void assign_material(Object *ob, Material *ma, short act)
770 Material *mao, **matar, ***matarar;
774 if (act > MAXMAT) return;
775 if (act < 1) act = 1;
777 /* prevent crashing when using accidentally */
778 BLI_assert(ob->id.lib == NULL);
779 if (ob->id.lib) return;
783 totcolp = give_totcolp(ob);
784 matarar = give_matarar(ob);
786 if (totcolp == NULL || matarar == NULL) return;
788 if (act > *totcolp) {
789 matar = MEM_callocN(sizeof(void *) * act, "matarray1");
792 memcpy(matar, *matarar, sizeof(void *) * (*totcolp));
800 if (act > ob->totcol) {
801 matar = MEM_callocN(sizeof(void *) * act, "matarray2");
802 matbits = MEM_callocN(sizeof(char) * act, "matbits1");
804 memcpy(matar, ob->mat, sizeof(void *) * ob->totcol);
805 memcpy(matbits, ob->matbits, sizeof(char) * (*totcolp));
807 MEM_freeN(ob->matbits);
810 ob->matbits = matbits;
813 /* copy object/mesh linking, or assign based on userpref */
815 ob->matbits[act - 1] = ob->matbits[ob->actcol - 1];
817 ob->matbits[act - 1] = (U.flag & USER_MAT_ON_OB) ? 1 : 0;
822 if (ob->matbits[act - 1]) { /* in object */
823 mao = ob->mat[act - 1];
824 if (mao) mao->id.us--;
825 ob->mat[act - 1] = ma;
828 mao = (*matarar)[act - 1];
829 if (mao) mao->id.us--;
830 (*matarar)[act - 1] = ma;
834 id_us_plus((ID *)ma);
835 test_object_materials(ob->data);
838 /* XXX - this calls many more update calls per object then are needed, could be optimized */
839 void assign_matarar(struct Object *ob, struct Material ***matar, short totcol)
841 int actcol_orig = ob->actcol;
844 while (object_remove_material_slot(ob)) {}
846 /* now we have the right number of slots */
847 for (i = 0; i < totcol; i++)
848 assign_material(ob, (*matar)[i], i + 1);
850 if (actcol_orig > ob->totcol)
851 actcol_orig = ob->totcol;
853 ob->actcol = actcol_orig;
857 short find_material_index(Object *ob, Material *ma)
862 if (ma == NULL) return 0;
864 totcolp = give_totcolp(ob);
865 matarar = give_matarar(ob);
867 if (totcolp == NULL || matarar == NULL) return 0;
869 for (a = 0; a < *totcolp; a++)
870 if ((*matarar)[a] == ma)
877 int object_add_material_slot(Object *ob)
879 if (ob == NULL) return FALSE;
880 if (ob->totcol >= MAXMAT) return FALSE;
882 assign_material(ob, NULL, ob->totcol + 1);
883 ob->actcol = ob->totcol;
887 static void do_init_render_material(Material *ma, int r_mode, float *amb)
890 int a, needuv = 0, needtang = 0;
892 if (ma->flarec == 0) ma->flarec = 1;
894 /* add all texcoflags from mtex, texco and mapto were cleared in advance */
895 for (a = 0; a < MAX_MTEX; a++) {
897 /* separate tex switching */
898 if (ma->septex & (1 << a)) continue;
901 if (mtex && mtex->tex && (mtex->tex->type | (mtex->tex->use_nodes && mtex->tex->nodetree) )) {
903 ma->texco |= mtex->texco;
904 ma->mapto |= mtex->mapto;
906 /* always get derivatives for these textures */
907 if (ELEM(mtex->tex->type, TEX_IMAGE, TEX_ENVMAP)) ma->texco |= TEXCO_OSA;
908 else if (mtex->texflag & (MTEX_COMPAT_BUMP | MTEX_3TAP_BUMP | MTEX_5TAP_BUMP | MTEX_BICUBIC_BUMP)) ma->texco |= TEXCO_OSA;
910 if (ma->texco & (TEXCO_ORCO | TEXCO_REFL | TEXCO_NORM | TEXCO_STRAND | TEXCO_STRESS)) needuv = 1;
911 else if (ma->texco & (TEXCO_GLOB | TEXCO_UV | TEXCO_OBJECT | TEXCO_SPEED)) needuv = 1;
912 else if (ma->texco & (TEXCO_LAVECTOR | TEXCO_VIEW | TEXCO_STICKY)) needuv = 1;
914 if ((ma->mapto & MAP_NORM) && (mtex->normapspace == MTEX_NSPACE_TANGENT))
919 if (needtang) ma->mode |= MA_NORMAP_TANG;
920 else ma->mode &= ~MA_NORMAP_TANG;
922 if (ma->mode & (MA_VERTEXCOL | MA_VERTEXCOLP | MA_FACETEXTURE)) {
924 if (r_mode & R_OSA) ma->texco |= TEXCO_OSA; /* for texfaces */
926 if (needuv) ma->texco |= NEED_UV;
928 /* since the raytracer doesnt recalc O structs for each ray, we have to preset them all */
929 if (r_mode & R_RAYTRACE) {
930 if ((ma->mode & (MA_RAYMIRROR | MA_SHADOW_TRA)) || ((ma->mode & MA_TRANSP) && (ma->mode & MA_RAYTRANSP))) {
931 ma->texco |= NEED_UV | TEXCO_ORCO | TEXCO_REFL | TEXCO_NORM;
932 if (r_mode & R_OSA) ma->texco |= TEXCO_OSA;
937 ma->ambr = ma->amb * amb[0];
938 ma->ambg = ma->amb * amb[1];
939 ma->ambb = ma->amb * amb[2];
941 /* will become or-ed result of all node modes */
942 ma->mode_l = ma->mode;
943 ma->mode_l &= ~MA_SHLESS;
945 if (ma->strand_surfnor > 0.0f)
946 ma->mode_l |= MA_STR_SURFDIFF;
948 /* parses the geom+tex nodes */
949 if (ma->nodetree && ma->use_nodes)
950 ntreeShaderGetTexcoMode(ma->nodetree, r_mode, &ma->texco, &ma->mode_l);
953 static void init_render_nodetree(bNodeTree *ntree, Material *basemat, int r_mode, float *amb)
957 for (node = ntree->nodes.first; node; node = node->next) {
959 if (GS(node->id->name) == ID_MA) {
960 Material *ma = (Material *)node->id;
962 do_init_render_material(ma, r_mode, amb);
963 basemat->texco |= ma->texco;
964 basemat->mode_l |= ma->mode_l & ~(MA_TRANSP | MA_ZTRANSP | MA_RAYTRANSP);
967 else if (node->type == NODE_GROUP)
968 init_render_nodetree((bNodeTree *)node->id, basemat, r_mode, amb);
973 void init_render_material(Material *mat, int r_mode, float *amb)
976 do_init_render_material(mat, r_mode, amb);
978 if (mat->nodetree && mat->use_nodes) {
979 init_render_nodetree(mat->nodetree, mat, r_mode, amb);
981 if (!mat->nodetree->execdata)
982 mat->nodetree->execdata = ntreeShaderBeginExecTree(mat->nodetree, 1);
986 void init_render_materials(Main *bmain, int r_mode, float *amb)
990 /* clear these flags before going over materials, to make sure they
991 * are cleared only once, otherwise node materials contained in other
992 * node materials can go wrong */
993 for (ma = bmain->mat.first; ma; ma = ma->id.next) {
1000 /* two steps, first initialize, then or the flags for layers */
1001 for (ma = bmain->mat.first; ma; ma = ma->id.next) {
1002 /* is_used flag comes back in convertblender.c */
1003 ma->flag &= ~MA_IS_USED;
1005 init_render_material(ma, r_mode, amb);
1008 do_init_render_material(&defmaterial, r_mode, amb);
1011 /* only needed for nodes now */
1012 void end_render_material(Material *mat)
1014 if (mat && mat->nodetree && mat->use_nodes) {
1015 if (mat->nodetree->execdata)
1016 ntreeShaderEndExecTree(mat->nodetree->execdata, 1);
1020 void end_render_materials(Main *bmain)
1023 for (ma = bmain->mat.first; ma; ma = ma->id.next)
1025 end_render_material(ma);
1028 static int material_in_nodetree(bNodeTree *ntree, Material *mat)
1032 for (node = ntree->nodes.first; node; node = node->next) {
1034 if (GS(node->id->name) == ID_MA) {
1035 if (node->id == (ID *)mat) {
1039 else if (node->type == NODE_GROUP) {
1040 if (material_in_nodetree((bNodeTree *)node->id, mat)) {
1050 int material_in_material(Material *parmat, Material *mat)
1054 else if (parmat->nodetree && parmat->use_nodes)
1055 return material_in_nodetree(parmat->nodetree, mat);
1061 /* ****************** */
1063 /* Update drivers for materials in a nodetree */
1064 static void material_node_drivers_update(Scene *scene, bNodeTree *ntree, float ctime)
1068 /* nodetree itself */
1069 if (ntree->adt && ntree->adt->drivers.first) {
1070 BKE_animsys_evaluate_animdata(scene, &ntree->id, ntree->adt, ctime, ADT_RECALC_DRIVERS);
1074 for (node = ntree->nodes.first; node; node = node->next) {
1076 if (GS(node->id->name) == ID_MA) {
1077 material_drivers_update(scene, (Material *)node->id, ctime);
1079 else if (node->type == NODE_GROUP) {
1080 material_node_drivers_update(scene, (bNodeTree *)node->id, ctime);
1086 /* Calculate all drivers for materials
1087 * FIXME: this is really a terrible method which may result in some things being calculated
1088 * multiple times. However, without proper despgraph support for these things, we are forced
1089 * into this sort of thing...
1091 void material_drivers_update(Scene *scene, Material *ma, float ctime)
1093 //if (G.f & G_DEBUG)
1094 // printf("material_drivers_update(%s, %s)\n", scene->id.name, ma->id.name);
1096 /* Prevent infinite recursion by checking (and tagging the material) as having been visited already
1097 * (see BKE_scene_update_tagged()). This assumes ma->id.flag & LIB_DOIT isn't set by anything else
1098 * in the meantime... [#32017]
1100 if (ma->id.flag & LIB_DOIT)
1103 ma->id.flag |= LIB_DOIT;
1105 /* material itself */
1106 if (ma->adt && ma->adt->drivers.first) {
1107 BKE_animsys_evaluate_animdata(scene, &ma->id, ma->adt, ctime, ADT_RECALC_DRIVERS);
1112 material_node_drivers_update(scene, ma->nodetree, ctime);
1116 /* ****************** */
1118 static char colname_array[125][20]= {
1119 "Black", "DarkRed", "HalfRed", "Red", "Red",
1120 "DarkGreen", "DarkOlive", "Brown", "Chocolate", "OrangeRed",
1121 "HalfGreen", "GreenOlive", "DryOlive", "Goldenrod", "DarkOrange",
1122 "LightGreen", "Chartreuse", "YellowGreen", "Yellow", "Gold",
1123 "Green", "LawnGreen", "GreenYellow", "LightOlive", "Yellow",
1124 "DarkBlue", "DarkPurple", "HotPink", "VioletPink", "RedPink",
1125 "SlateGray", "DarkGray", "PalePurple", "IndianRed", "Tomato",
1126 "SeaGreen", "PaleGreen", "GreenKhaki", "LightBrown", "LightSalmon",
1127 "SpringGreen", "PaleGreen", "MediumOlive", "YellowBrown", "LightGold",
1128 "LightGreen", "LightGreen", "LightGreen", "GreenYellow", "PaleYellow",
1129 "HalfBlue", "DarkSky", "HalfMagenta", "VioletRed", "DeepPink",
1130 "SteelBlue", "SkyBlue", "Orchid", "LightHotPink", "HotPink",
1131 "SeaGreen", "SlateGray", "MediumGray", "Burlywood", "LightPink",
1132 "SpringGreen", "Aquamarine", "PaleGreen", "Khaki", "PaleOrange",
1133 "SpringGreen", "SeaGreen", "PaleGreen", "PaleWhite", "YellowWhite",
1134 "LightBlue", "Purple", "MediumOrchid", "Magenta", "Magenta",
1135 "RoyalBlue", "SlateBlue", "MediumOrchid", "Orchid", "Magenta",
1136 "DeepSkyBlue", "LightSteelBlue", "LightSkyBlue", "Violet", "LightPink",
1137 "Cyan", "DarkTurquoise", "SkyBlue", "Gray", "Snow",
1138 "Mint", "Mint", "Aquamarine", "MintCream", "Ivory",
1139 "Blue", "Blue", "DarkMagenta", "DarkOrchid", "Magenta",
1140 "SkyBlue", "RoyalBlue", "LightSlateBlue", "MediumOrchid", "Magenta",
1141 "DodgerBlue", "SteelBlue", "MediumPurple", "PalePurple", "Plum",
1142 "DeepSkyBlue", "PaleBlue", "LightSkyBlue", "PalePurple", "Thistle",
1143 "Cyan", "ColdBlue", "PaleTurquoise", "GhostWhite", "White"
1146 void automatname(Material *ma)
1151 if (ma == NULL) return;
1152 if (ma->mode & MA_SHLESS) ref = 1.0;
1155 r = (int)(4.99f * (ref * ma->r));
1156 g = (int)(4.99f * (ref * ma->g));
1157 b = (int)(4.99f * (ref * ma->b));
1158 nr = r + 5 * g + 25 * b;
1159 if (nr > 124) nr = 124;
1160 new_id(&G.main->mat, (ID *)ma, colname_array[nr]);
1165 int object_remove_material_slot(Object *ob)
1167 Material *mao, ***matarar;
1172 if (ob == NULL || ob->totcol == 0) {
1176 /* this should never happen and used to crash */
1177 if (ob->actcol <= 0) {
1178 printf("%s: invalid material index %d, report a bug!\n", __func__, ob->actcol);
1183 /* take a mesh/curve/mball as starting point, remove 1 index,
1184 * AND with all objects that share the ob->data
1186 * after that check indices in mesh/curve/mball!!!
1189 totcolp = give_totcolp(ob);
1190 matarar = give_matarar(ob);
1192 if (*matarar == NULL) return FALSE;
1194 /* we delete the actcol */
1195 mao = (*matarar)[ob->actcol - 1];
1196 if (mao) mao->id.us--;
1198 for (a = ob->actcol; a < ob->totcol; a++)
1199 (*matarar)[a - 1] = (*matarar)[a];
1202 if (*totcolp == 0) {
1203 MEM_freeN(*matarar);
1207 actcol = ob->actcol;
1208 obt = G.main->object.first;
1211 if (obt->data == ob->data) {
1213 /* WATCH IT: do not use actcol from ob or from obt (can become zero) */
1214 mao = obt->mat[actcol - 1];
1215 if (mao) mao->id.us--;
1217 for (a = actcol; a < obt->totcol; a++) {
1218 obt->mat[a - 1] = obt->mat[a];
1219 obt->matbits[a - 1] = obt->matbits[a];
1222 if (obt->actcol > obt->totcol) obt->actcol = obt->totcol;
1224 if (obt->totcol == 0) {
1225 MEM_freeN(obt->mat);
1226 MEM_freeN(obt->matbits);
1228 obt->matbits = NULL;
1234 /* check indices from mesh */
1235 if (ELEM4(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) {
1236 data_delete_material_index_id((ID *)ob->data, actcol - 1);
1237 BKE_displist_free(&ob->disp);
1244 /* r_col = current value, col = new value, (fac == 0) is no change */
1245 void ramp_blend(int type, float r_col[3], const float fac, const float col[3])
1247 float tmp, facm = 1.0f - fac;
1251 r_col[0] = facm * (r_col[0]) + fac * col[0];
1252 r_col[1] = facm * (r_col[1]) + fac * col[1];
1253 r_col[2] = facm * (r_col[2]) + fac * col[2];
1256 r_col[0] += fac * col[0];
1257 r_col[1] += fac * col[1];
1258 r_col[2] += fac * col[2];
1261 r_col[0] *= (facm + fac * col[0]);
1262 r_col[1] *= (facm + fac * col[1]);
1263 r_col[2] *= (facm + fac * col[2]);
1265 case MA_RAMP_SCREEN:
1266 r_col[0] = 1.0f - (facm + fac * (1.0f - col[0])) * (1.0f - r_col[0]);
1267 r_col[1] = 1.0f - (facm + fac * (1.0f - col[1])) * (1.0f - r_col[1]);
1268 r_col[2] = 1.0f - (facm + fac * (1.0f - col[2])) * (1.0f - r_col[2]);
1270 case MA_RAMP_OVERLAY:
1271 if (r_col[0] < 0.5f)
1272 r_col[0] *= (facm + 2.0f * fac * col[0]);
1274 r_col[0] = 1.0f - (facm + 2.0f * fac * (1.0f - col[0])) * (1.0f - r_col[0]);
1275 if (r_col[1] < 0.5f)
1276 r_col[1] *= (facm + 2.0f * fac * col[1]);
1278 r_col[1] = 1.0f - (facm + 2.0f * fac * (1.0f - col[1])) * (1.0f - r_col[1]);
1279 if (r_col[2] < 0.5f)
1280 r_col[2] *= (facm + 2.0f * fac * col[2]);
1282 r_col[2] = 1.0f - (facm + 2.0f * fac * (1.0f - col[2])) * (1.0f - r_col[2]);
1285 r_col[0] -= fac * col[0];
1286 r_col[1] -= fac * col[1];
1287 r_col[2] -= fac * col[2];
1291 r_col[0] = facm * (r_col[0]) + fac * (r_col[0]) / col[0];
1293 r_col[1] = facm * (r_col[1]) + fac * (r_col[1]) / col[1];
1295 r_col[2] = facm * (r_col[2]) + fac * (r_col[2]) / col[2];
1298 r_col[0] = facm * (r_col[0]) + fac *fabsf(r_col[0] - col[0]);
1299 r_col[1] = facm * (r_col[1]) + fac *fabsf(r_col[1] - col[1]);
1300 r_col[2] = facm * (r_col[2]) + fac *fabsf(r_col[2] - col[2]);
1303 tmp = col[0] + ((1 - col[0]) * facm);
1304 if (tmp < r_col[0]) r_col[0] = tmp;
1305 tmp = col[1] + ((1 - col[1]) * facm);
1306 if (tmp < r_col[1]) r_col[1] = tmp;
1307 tmp = col[2] + ((1 - col[2]) * facm);
1308 if (tmp < r_col[2]) r_col[2] = tmp;
1312 if (tmp > r_col[0]) r_col[0] = tmp;
1314 if (tmp > r_col[1]) r_col[1] = tmp;
1316 if (tmp > r_col[2]) r_col[2] = tmp;
1319 if (r_col[0] != 0.0f) {
1320 tmp = 1.0f - fac * col[0];
1323 else if ((tmp = (r_col[0]) / tmp) > 1.0f)
1328 if (r_col[1] != 0.0f) {
1329 tmp = 1.0f - fac * col[1];
1332 else if ((tmp = (r_col[1]) / tmp) > 1.0f)
1337 if (r_col[2] != 0.0f) {
1338 tmp = 1.0f - fac * col[2];
1341 else if ((tmp = (r_col[2]) / tmp) > 1.0f)
1348 tmp = facm + fac * col[0];
1352 else if ((tmp = (1.0f - (1.0f - (r_col[0])) / tmp)) < 0.0f)
1354 else if (tmp > 1.0f)
1359 tmp = facm + fac * col[1];
1362 else if ((tmp = (1.0f - (1.0f - (r_col[1])) / tmp)) < 0.0f)
1364 else if (tmp > 1.0f)
1369 tmp = facm + fac * col[2];
1372 else if ((tmp = (1.0f - (1.0f - (r_col[2])) / tmp)) < 0.0f)
1374 else if (tmp > 1.0f)
1382 float colH, colS, colV;
1383 float tmpr, tmpg, tmpb;
1384 rgb_to_hsv(col[0], col[1], col[2], &colH, &colS, &colV);
1386 rgb_to_hsv(r_col[0], r_col[1], r_col[2], &rH, &rS, &rV);
1387 hsv_to_rgb(colH, rS, rV, &tmpr, &tmpg, &tmpb);
1388 r_col[0] = facm * (r_col[0]) + fac * tmpr;
1389 r_col[1] = facm * (r_col[1]) + fac * tmpg;
1390 r_col[2] = facm * (r_col[2]) + fac * tmpb;
1397 float colH, colS, colV;
1398 rgb_to_hsv(r_col[0], r_col[1], r_col[2], &rH, &rS, &rV);
1400 rgb_to_hsv(col[0], col[1], col[2], &colH, &colS, &colV);
1401 hsv_to_rgb(rH, (facm * rS + fac * colS), rV, r_col + 0, r_col + 1, r_col + 2);
1408 float colH, colS, colV;
1409 rgb_to_hsv(r_col[0], r_col[1], r_col[2], &rH, &rS, &rV);
1410 rgb_to_hsv(col[0], col[1], col[2], &colH, &colS, &colV);
1411 hsv_to_rgb(rH, rS, (facm * rV + fac * colV), r_col + 0, r_col + 1, r_col + 2);
1417 float colH, colS, colV;
1418 float tmpr, tmpg, tmpb;
1419 rgb_to_hsv(col[0], col[1], col[2], &colH, &colS, &colV);
1421 rgb_to_hsv(r_col[0], r_col[1], r_col[2], &rH, &rS, &rV);
1422 hsv_to_rgb(colH, colS, rV, &tmpr, &tmpg, &tmpb);
1423 r_col[0] = facm * (r_col[0]) + fac * tmpr;
1424 r_col[1] = facm * (r_col[1]) + fac * tmpg;
1425 r_col[2] = facm * (r_col[2]) + fac * tmpb;
1431 float scr, scg, scb;
1433 /* first calculate non-fac based Screen mix */
1434 scr = 1.0f - (1.0f - col[0]) * (1.0f - r_col[0]);
1435 scg = 1.0f - (1.0f - col[1]) * (1.0f - r_col[1]);
1436 scb = 1.0f - (1.0f - col[2]) * (1.0f - r_col[2]);
1438 r_col[0] = facm * (r_col[0]) + fac * (((1.0f - r_col[0]) * col[0] * (r_col[0])) + (r_col[0] * scr));
1439 r_col[1] = facm * (r_col[1]) + fac * (((1.0f - r_col[1]) * col[1] * (r_col[1])) + (r_col[1] * scg));
1440 r_col[2] = facm * (r_col[2]) + fac * (((1.0f - r_col[2]) * col[2] * (r_col[2])) + (r_col[2] * scb));
1443 case MA_RAMP_LINEAR:
1445 r_col[0] = r_col[0] + fac * (2.0f * (col[0] - 0.5f));
1447 r_col[0] = r_col[0] + fac * (2.0f * (col[0]) - 1.0f);
1449 r_col[1] = r_col[1] + fac * (2.0f * (col[1] - 0.5f));
1451 r_col[1] = r_col[1] + fac * (2.0f * (col[1]) - 1.0f);
1453 r_col[2] = r_col[2] + fac * (2.0f * (col[2] - 0.5f));
1455 r_col[2] = r_col[2] + fac * (2.0f * (col[2]) - 1.0f);
1460 /* copy/paste buffer, if we had a propper py api that would be better */
1461 static Material matcopybuf;
1462 static short matcopied = 0;
1464 void clear_matcopybuf(void)
1466 memset(&matcopybuf, 0, sizeof(Material));
1470 void free_matcopybuf(void)
1474 for (a = 0; a < MAX_MTEX; a++) {
1475 if (matcopybuf.mtex[a]) {
1476 MEM_freeN(matcopybuf.mtex[a]);
1477 matcopybuf.mtex[a] = NULL;
1481 if (matcopybuf.ramp_col) MEM_freeN(matcopybuf.ramp_col);
1482 if (matcopybuf.ramp_spec) MEM_freeN(matcopybuf.ramp_spec);
1484 matcopybuf.ramp_col = NULL;
1485 matcopybuf.ramp_spec = NULL;
1487 if (matcopybuf.nodetree) {
1488 ntreeFreeTree(matcopybuf.nodetree);
1489 MEM_freeN(matcopybuf.nodetree);
1490 matcopybuf.nodetree = NULL;
1496 void copy_matcopybuf(Material *ma)
1504 memcpy(&matcopybuf, ma, sizeof(Material));
1505 if (matcopybuf.ramp_col) matcopybuf.ramp_col = MEM_dupallocN(matcopybuf.ramp_col);
1506 if (matcopybuf.ramp_spec) matcopybuf.ramp_spec = MEM_dupallocN(matcopybuf.ramp_spec);
1508 for (a = 0; a < MAX_MTEX; a++) {
1509 mtex = matcopybuf.mtex[a];
1511 matcopybuf.mtex[a] = MEM_dupallocN(mtex);
1514 matcopybuf.nodetree = ntreeCopyTree(ma->nodetree);
1515 matcopybuf.preview = NULL;
1516 matcopybuf.gpumaterial.first = matcopybuf.gpumaterial.last = NULL;
1520 void paste_matcopybuf(Material *ma)
1528 /* free current mat */
1529 if (ma->ramp_col) MEM_freeN(ma->ramp_col);
1530 if (ma->ramp_spec) MEM_freeN(ma->ramp_spec);
1531 for (a = 0; a < MAX_MTEX; a++) {
1533 if (mtex && mtex->tex) mtex->tex->id.us--;
1534 if (mtex) MEM_freeN(mtex);
1538 ntreeFreeTree(ma->nodetree);
1539 MEM_freeN(ma->nodetree);
1542 GPU_material_free(ma);
1545 memcpy(ma, &matcopybuf, sizeof(Material));
1548 if (matcopybuf.ramp_col) ma->ramp_col = MEM_dupallocN(matcopybuf.ramp_col);
1549 if (matcopybuf.ramp_spec) ma->ramp_spec = MEM_dupallocN(matcopybuf.ramp_spec);
1551 for (a = 0; a < MAX_MTEX; a++) {
1554 ma->mtex[a] = MEM_dupallocN(mtex);
1555 if (mtex->tex) id_us_plus((ID *)mtex->tex);
1559 ma->nodetree = ntreeCopyTree(matcopybuf.nodetree);
1563 /*********************** texface to material convert functions **********************/
1564 /* encode all the TF information into a single int */
1565 static int encode_tfaceflag(MTFace *tf, int convertall)
1567 /* calculate the flag */
1568 int flag = tf->mode;
1570 /* options that change the material offline render */
1575 /* clean flags that are not being converted */
1577 flag &= ~TF_SHAREDVERT;
1578 flag &= ~TF_SHAREDCOL;
1579 flag &= ~TF_CONVERTED;
1581 /* light tface flag is ignored in GLSL mode */
1584 /* 15 is how big the flag can be - hardcoded here and in decode_tfaceflag() */
1585 flag |= tf->transp << 15;
1587 /* increase 1 so flag 0 is different than no flag yet */
1591 /* set the material options based in the tface flag */
1592 static void decode_tfaceflag(Material *ma, int flag, int convertall)
1595 GameSettings *game = &ma->game;
1597 /* flag is shifted in 1 to make 0 != no flag yet (see encode_tfaceflag) */
1600 alphablend = flag >> 15; //encoded in the encode_tfaceflag function
1603 /* General Material Options */
1604 if ((flag & TF_DYNAMIC) == 0) (*game).flag |= GEMAT_NOPHYSICS;
1606 /* Material Offline Rendering Properties */
1608 if (flag & TF_OBCOL) ma->shade_flag |= MA_OBCOLOR;
1611 /* Special Face Properties */
1612 if ((flag & TF_TWOSIDE) == 0) (*game).flag |= GEMAT_BACKCULL;
1613 if (flag & TF_INVISIBLE) (*game).flag |= GEMAT_INVISIBLE;
1614 if (flag & TF_BMFONT) (*game).flag |= GEMAT_TEXT;
1616 /* Face Orientation */
1617 if (flag & TF_BILLBOARD) (*game).face_orientation |= GEMAT_HALO;
1618 else if (flag & TF_BILLBOARD2) (*game).face_orientation |= GEMAT_BILLBOARD;
1619 else if (flag & TF_SHADOW) (*game).face_orientation |= GEMAT_SHADOW;
1622 if (flag & TF_ALPHASORT && ELEM(alphablend, TF_ALPHA, TF_ADD)) (*game).alpha_blend = GEMAT_ALPHA_SORT;
1623 else if (alphablend & TF_ALPHA) (*game).alpha_blend = GEMAT_ALPHA;
1624 else if (alphablend & TF_ADD) (*game).alpha_blend = GEMAT_ADD;
1625 else if (alphablend & TF_CLIP) (*game).alpha_blend = GEMAT_CLIP;
1628 /* boolean check to see if the mesh needs a material */
1629 static int check_tfaceneedmaterial(int flag)
1631 /* check if the flags we have are not deprecated != than default material options
1632 * also if only flags are visible and collision see if all objects using this mesh have this option in physics */
1634 /* flag is shifted in 1 to make 0 != no flag yet (see encode_tfaceflag) */
1637 /* deprecated flags */
1639 flag &= ~TF_SHAREDVERT;
1640 flag &= ~TF_SHAREDCOL;
1642 /* light tface flag is ignored in GLSL mode */
1645 /* automatic detected if tex image has alpha */
1646 flag &= ~(TF_ALPHA << 15);
1647 /* automatic detected if using texture */
1650 /* settings for the default NoMaterial */
1651 if (flag == TF_DYNAMIC)
1658 /* return number of digits of an integer */
1659 /* XXX to be optmized or replaced by an equivalent blender internal function */
1660 static int integer_getdigits(int number)
1663 if (number == 0) return 1;
1665 while (number != 0) {
1666 number = (int)(number / 10);
1672 static void calculate_tface_materialname(char *matname, char *newname, int flag)
1674 /* if flag has only light and collision and material matches those values
1675 * you can do strcpy(name, mat_name);
1677 int digits = integer_getdigits(flag);
1678 /* clamp the old name, remove the MA prefix and add the .TF.flag suffix
1679 * e.g. matname = "MALoooooooooooooongName"; newname = "Loooooooooooooon.TF.2" */
1680 BLI_snprintf(newname, MAX_ID_NAME, "%.*s.TF.%0*d", MAX_ID_NAME - (digits + 5), matname, digits, flag);
1683 /* returns -1 if no match */
1684 static short mesh_getmaterialnumber(Mesh *me, Material *ma)
1688 for (a = 0; a < me->totcol; a++) {
1689 if (me->mat[a] == ma) {
1697 /* append material */
1698 static short mesh_addmaterial(Mesh *me, Material *ma)
1700 material_append_id(&me->id, NULL);
1701 me->mat[me->totcol - 1] = ma;
1703 id_us_plus(&ma->id);
1705 return me->totcol - 1;
1708 static void set_facetexture_flags(Material *ma, Image *image)
1711 ma->mode |= MA_FACETEXTURE;
1712 /* we could check if the texture has alpha, but then more meshes sharing the same
1713 * material may need it. Let's make it simple. */
1714 if (BKE_image_has_alpha(image))
1715 ma->mode |= MA_FACETEXTURE_ALPHA;
1719 /* returns material number */
1720 static short convert_tfacenomaterial(Main *main, Mesh *me, MTFace *tf, int flag)
1723 char idname[MAX_ID_NAME];
1726 /* new material, the name uses the flag*/
1727 BLI_snprintf(idname, sizeof(idname), "MAMaterial.TF.%0*d", integer_getdigits(flag), flag);
1729 if ((ma = BLI_findstring(&main->mat, idname + 2, offsetof(ID, name) + 2))) {
1730 mat_nr = mesh_getmaterialnumber(me, ma);
1731 /* assign the material to the mesh */
1732 if (mat_nr == -1) mat_nr = mesh_addmaterial(me, ma);
1734 /* if needed set "Face Textures [Alpha]" Material options */
1735 set_facetexture_flags(ma, tf->tpage);
1737 /* create a new material */
1739 ma = BKE_material_add(idname + 2);
1742 printf("TexFace Convert: Material \"%s\" created.\n", idname + 2);
1743 mat_nr = mesh_addmaterial(me, ma);
1745 /* if needed set "Face Textures [Alpha]" Material options */
1746 set_facetexture_flags(ma, tf->tpage);
1748 decode_tfaceflag(ma, flag, 1);
1749 /* the final decoding will happen after, outside the main loop
1750 * for now store the flag into the material and change light/tex/collision
1751 * store the flag as a negative number */
1752 ma->game.flag = -flag;
1753 id_us_min((ID *)ma);
1755 else printf("Error: Unable to create Material \"%s\" for Mesh \"%s\".", idname + 2, me->id.name + 2);
1758 /* set as converted, no need to go bad to this face */
1759 tf->mode |= TF_CONVERTED;
1763 /* Function to fully convert materials */
1764 static void convert_tfacematerial(Main *main, Material *ma)
1773 CustomDataLayer *cdl;
1774 char idname[MAX_ID_NAME];
1776 for (me = main->mesh.first; me; me = me->id.next) {
1777 /* check if this mesh uses this material */
1778 for (a = 0; a < me->totcol; a++)
1779 if (me->mat[a] == ma) break;
1781 /* no material found */
1782 if (a == me->totcol) continue;
1784 /* get the active tface layer */
1785 index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
1786 cdl = (index == -1) ? NULL : &me->fdata.layers[index];
1789 /* loop over all the faces and stop at the ones that use the material*/
1790 for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
1791 if (me->mat[mf->mat_nr] != ma) continue;
1793 /* texface data for this face */
1794 tf = ((MTFace *)cdl->data) + a;
1795 flag = encode_tfaceflag(tf, 1);
1797 /* the name of the new material */
1798 calculate_tface_materialname(ma->id.name, (char *)&idname, flag);
1800 if ((mat_new = BLI_findstring(&main->mat, idname + 2, offsetof(ID, name) + 2))) {
1801 /* material already existent, see if the mesh has it */
1802 mat_nr = mesh_getmaterialnumber(me, mat_new);
1803 /* material is not in the mesh, add it */
1804 if (mat_nr == -1) mat_nr = mesh_addmaterial(me, mat_new);
1806 /* create a new material */
1808 mat_new = BKE_material_copy(ma);
1810 /* rename the material*/
1811 strcpy(mat_new->id.name, idname);
1812 id_us_min((ID *)mat_new);
1814 mat_nr = mesh_addmaterial(me, mat_new);
1815 decode_tfaceflag(mat_new, flag, 1);
1818 printf("Error: Unable to create Material \"%s\" for Mesh \"%s.", idname + 2, me->id.name + 2);
1819 mat_nr = mf->mat_nr;
1824 /* if the material has a texture but no texture channel
1825 * set "Face Textures [Alpha]" Material options
1826 * actually we need to run it always, because of old behavior
1827 * of using face texture if any texture channel was present (multitex) */
1828 //if ((!mat_new->mtex[0]) && (!mat_new->mtex[0]->tex))
1829 set_facetexture_flags(mat_new, tf->tpage);
1831 /* set the material number to the face*/
1832 mf->mat_nr = mat_nr;
1834 /* remove material from mesh */
1835 for (a = 0; a < me->totcol; )
1836 if (me->mat[a] == ma) material_pop_id(&me->id, a, 1); else a++;
1841 #define MAT_BGE_DISPUTED -99999
1843 int do_version_tface(Main *main, int fileload)
1849 CustomDataLayer *cdl;
1854 /* sometimes mesh has no materials but will need a new one. In those
1855 * cases we need to ignore the mf->mat_nr and only look at the face
1856 * mode because it can be zero as uninitialized or the 1st created material
1858 int nomaterialslots;
1860 /* alert to user to check the console */
1863 /* mark all the materials to conversion with a flag
1864 * if there is tface create a complete flag for that storing in flag
1865 * if there is tface and flag > 0: creates a new flag based on this face
1866 * if flags are different set flag to -1
1869 /* 1st part: marking mesh materials to update */
1870 for (me = main->mesh.first; me; me = me->id.next) {
1871 if (me->id.lib) continue;
1873 /* get the active tface layer */
1874 index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
1875 cdl = (index == -1) ? NULL : &me->fdata.layers[index];
1878 nomaterialslots = (me->totcol == 0 ? 1 : 0);
1880 /* loop over all the faces*/
1881 for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
1882 /* texface data for this face */
1883 tf = ((MTFace *)cdl->data) + a;
1885 /* conversion should happen only once */
1887 tf->mode &= ~TF_CONVERTED;
1889 if ((tf->mode & TF_CONVERTED)) continue;
1890 else tf->mode |= TF_CONVERTED;
1893 /* no material slots */
1894 if (nomaterialslots) {
1895 flag = encode_tfaceflag(tf, 1);
1897 /* create/find a new material and assign to the face */
1898 if (check_tfaceneedmaterial(flag)) {
1899 mf->mat_nr = convert_tfacenomaterial(main, me, tf, flag);
1901 /* else mark them as no-material to be reverted to 0 later */
1906 else if (mf->mat_nr < me->totcol) {
1907 ma = me->mat[mf->mat_nr];
1909 /* no material create one if necessary */
1911 /* find a new material and assign to the face */
1912 flag = encode_tfaceflag(tf, 1);
1914 /* create/find a new material and assign to the face */
1915 if (check_tfaceneedmaterial(flag))
1916 mf->mat_nr = convert_tfacenomaterial(main, me, tf, flag);
1921 /* we can't read from this if it comes from a library,
1922 * at doversion time: direct_link might not have happened on it,
1923 * so ma->mtex is not pointing to valid memory yet.
1924 * later we could, but it's better not */
1925 else if (ma->id.lib)
1928 /* material already marked as disputed */
1929 else if (ma->game.flag == MAT_BGE_DISPUTED)
1932 /* found a material */
1934 flag = encode_tfaceflag(tf, ((fileload) ? 0 : 1));
1936 /* first time changing this material */
1937 if (ma->game.flag == 0)
1938 ma->game.flag = -flag;
1940 /* mark material as disputed */
1941 else if (ma->game.flag != -flag) {
1942 ma->game.flag = MAT_BGE_DISPUTED;
1946 /* material ok so far */
1948 ma->game.flag = -flag;
1950 /* some people uses multitexture with TexFace by creating a texture
1951 * channel which not necessarily the tf->tpage image. But the game engine
1952 * was enabling it. Now it's required to set "Face Texture [Alpha] in the
1953 * material settings. */
1955 set_facetexture_flags(ma, tf->tpage);
1964 /* if we didn't have material slot and now we do, we need to
1965 * make sure the materials are correct */
1966 if (nomaterialslots) {
1967 if (me->totcol > 0) {
1968 for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
1969 if (mf->mat_nr == -1) {
1970 /* texface data for this face */
1971 tf = ((MTFace *)cdl->data) + a;
1972 mf->mat_nr = convert_tfacenomaterial(main, me, tf, encode_tfaceflag(tf, 1));
1977 for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
1985 /* 2nd part - conversion */
1986 /* skip library files */
1988 /* we shouldn't loop through the materials created in the loop. make the loop stop at its original length) */
1989 for (ma = main->mat.first, a = 0; ma; ma = ma->id.next, a++) {
1990 if (ma->id.lib) continue;
1992 /* disputed material */
1993 if (ma->game.flag == MAT_BGE_DISPUTED) {
1996 printf("Warning: material \"%s\" skipped - to convert old game texface to material go to the Help menu.\n", ma->id.name + 2);
2000 convert_tfacematerial(main, ma);
2004 /* no conflicts in this material - 90% of cases
2005 * convert from tface system to material */
2006 else if (ma->game.flag < 0) {
2007 decode_tfaceflag(ma, -(ma->game.flag), 1);
2009 /* material is good make sure all faces using
2010 * this material are set to converted */
2012 for (me = main->mesh.first; me; me = me->id.next) {
2013 /* check if this mesh uses this material */
2014 for (a = 0; a < me->totcol; a++)
2015 if (me->mat[a] == ma) break;
2017 /* no material found */
2018 if (a == me->totcol) continue;
2020 /* get the active tface layer */
2021 index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
2022 cdl = (index == -1) ? NULL : &me->fdata.layers[index];
2025 /* loop over all the faces and stop at the ones that use the material*/
2026 for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
2027 if (me->mat[mf->mat_nr] == ma) {
2028 /* texface data for this face */
2029 tf = ((MTFace *)cdl->data) + a;
2030 tf->mode |= TF_CONVERTED;
2036 /* material is not used by faces with texface
2037 * set the default flag - do it only once */
2040 ma->game.flag = GEMAT_BACKCULL;