Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2017-05-24 16:14:32 +0300
committerCampbell Barton <ideasman42@gmail.com>2017-05-24 16:38:15 +0300
commit7a9ad029dd1d1afe42d54c9c181de887636db7c0 (patch)
treee9281cbe8bb01365a699ffd6f4bbd09a6a91015f /source/blender/blenkernel
parent707340edd703ff1fd7c8157eb3cc811913698c8d (diff)
Remove TexFace, per-face images
TexFace complicates the now more popular shading pipeline by having per-face images, see: T51382 for details. To keep the ability to select a per-material edit-image (used with UV-mapping workflow), the material now stores an image which will be set when changing images in edit-mode. This is used as a bake-target when not using Cycles too.
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_material.h7
-rw-r--r--source/blender/blenkernel/intern/customdata.c2
-rw-r--r--source/blender/blenkernel/intern/library_query.c26
-rw-r--r--source/blender/blenkernel/intern/material.c508
4 files changed, 25 insertions, 518 deletions
diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h
index 8ae5c2b3c45..0a5d37631d1 100644
--- a/source/blender/blenkernel/BKE_material.h
+++ b/source/blender/blenkernel/BKE_material.h
@@ -86,6 +86,10 @@ short BKE_object_material_slot_find_index(struct Object *ob, struct Material *ma
bool BKE_object_material_slot_add(struct Object *ob);
bool BKE_object_material_slot_remove(struct Object *ob);
+struct Image *BKE_object_material_edit_image_get(struct Object *ob, short mat_nr);
+struct Image **BKE_object_material_edit_image_get_array(struct Object *ob);
+bool BKE_object_material_edit_image_set(struct Object *ob, short mat_nr, struct Image *image);
+
void BKE_texpaint_slot_refresh_cache(struct Scene *scene, struct Material *ma);
void BKE_texpaint_slots_refresh_object(struct Scene *scene, struct Object *ob);
@@ -114,9 +118,6 @@ void free_matcopybuf(void);
void copy_matcopybuf(struct Material *ma);
void paste_matcopybuf(struct Material *ma);
-/* handle backward compatibility for tface/materials called from doversion */
-int do_version_tface(struct Main *main);
-
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index 7c3f0ac630d..96b15a22554 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -419,7 +419,7 @@ static void layerSwap_tface(void *data, const int *corner_indices)
static void layerDefault_tface(void *data, int count)
{
- static MTFace default_tf = {{{0, 0}, {1, 0}, {1, 1}, {0, 1}}, NULL,
+ static MTFace default_tf = {{{0, 0}, {1, 0}, {1, 1}, {0, 1}},
0, 0, TF_DYNAMIC | TF_CONVERTED, 0, 0};
MTFace *tf = (MTFace *)data;
int i;
diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c
index 3c8d1c6d888..0c89a5bea42 100644
--- a/source/blender/blenkernel/intern/library_query.c
+++ b/source/blender/blenkernel/intern/library_query.c
@@ -643,31 +643,6 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
for (i = 0; i < mesh->totcol; i++) {
CALLBACK_INVOKE(mesh->mat[i], IDWALK_CB_USER);
}
-
- /* XXX Really not happy with this - probably texface should rather use some kind of
- * 'texture slots' and just set indices in each poly/face item - would also save some memory.
- * Maybe a nice TODO for blender2.8? */
- if (mesh->mtface || mesh->mtpoly) {
- for (i = 0; i < mesh->pdata.totlayer; i++) {
- if (mesh->pdata.layers[i].type == CD_MTEXPOLY) {
- MTexPoly *txface = (MTexPoly *)mesh->pdata.layers[i].data;
-
- for (int j = 0; j < mesh->totpoly; j++, txface++) {
- CALLBACK_INVOKE(txface->tpage, IDWALK_CB_USER_ONE);
- }
- }
- }
-
- for (i = 0; i < mesh->fdata.totlayer; i++) {
- if (mesh->fdata.layers[i].type == CD_MTFACE) {
- MTFace *tface = (MTFace *)mesh->fdata.layers[i].data;
-
- for (int j = 0; j < mesh->totface; j++, tface++) {
- CALLBACK_INVOKE(tface->tpage, IDWALK_CB_USER_ONE);
- }
- }
- }
- }
break;
}
@@ -710,6 +685,7 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
library_foreach_ID_as_subdata_link((ID **)&material->nodetree, callback, user_data, flag, &data);
}
CALLBACK_INVOKE(material->group, IDWALK_CB_USER);
+ CALLBACK_INVOKE(material->edit_image, IDWALK_CB_USER);
break;
}
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index fb4aec0a380..61e3ede3e8a 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -229,6 +229,7 @@ Material *BKE_material_copy(Main *bmain, Material *ma)
man = BKE_libblock_copy(bmain, &ma->id);
id_lib_extern((ID *)man->group);
+ id_lib_extern((ID *)man->edit_image);
for (a = 0; a < MAX_MTEX; a++) {
if (ma->mtex[a]) {
@@ -944,7 +945,7 @@ static void do_init_render_material(Material *ma, int r_mode, float *amb)
if (needtang) ma->mode |= MA_NORMAP_TANG;
else ma->mode &= ~MA_NORMAP_TANG;
- if (ma->mode & (MA_VERTEXCOL | MA_VERTEXCOLP | MA_FACETEXTURE)) {
+ if (ma->mode & (MA_VERTEXCOL | MA_VERTEXCOLP)) {
needuv = 1;
if (r_mode & R_OSA) ma->texco |= TEXCO_OSA; /* for texfaces */
}
@@ -1767,501 +1768,30 @@ void paste_matcopybuf(Material *ma)
ma->nodetree = ntreeCopyTree_ex(matcopybuf.nodetree, G.main, false);
}
-
-/*********************** texface to material convert functions **********************/
-/* encode all the TF information into a single int */
-static int encode_tfaceflag(MTFace *tf, int convertall)
-{
- /* calculate the flag */
- int flag = tf->mode;
-
- /* options that change the material offline render */
- if (!convertall) {
- flag &= ~TF_OBCOL;
- }
-
- /* clean flags that are not being converted */
- flag &= ~TF_TEX;
- flag &= ~TF_SHAREDVERT;
- flag &= ~TF_SHAREDCOL;
- flag &= ~TF_CONVERTED;
-
- /* light tface flag is ignored in GLSL mode */
- flag &= ~TF_LIGHT;
-
- /* 15 is how big the flag can be - hardcoded here and in decode_tfaceflag() */
- flag |= tf->transp << 15;
-
- /* increase 1 so flag 0 is different than no flag yet */
- return flag + 1;
-}
-
-/* set the material options based in the tface flag */
-static void decode_tfaceflag(Material *ma, int flag, int convertall)
+struct Image *BKE_object_material_edit_image_get(Object *ob, short mat_nr)
{
- int alphablend;
- GameSettings *game = &ma->game;
-
- /* flag is shifted in 1 to make 0 != no flag yet (see encode_tfaceflag) */
- flag -= 1;
-
- alphablend = flag >> 15; /* encoded in the encode_tfaceflag function */
- (*game).flag = 0;
-
- /* General Material Options */
- if ((flag & TF_DYNAMIC) == 0) (*game).flag |= GEMAT_NOPHYSICS;
-
- /* Material Offline Rendering Properties */
- if (convertall) {
- if (flag & TF_OBCOL) ma->shade_flag |= MA_OBCOLOR;
- }
-
- /* Special Face Properties */
- if ((flag & TF_TWOSIDE) == 0) (*game).flag |= GEMAT_BACKCULL;
- if (flag & TF_INVISIBLE) (*game).flag |= GEMAT_INVISIBLE;
- if (flag & TF_BMFONT) (*game).flag |= GEMAT_TEXT;
-
- /* Face Orientation */
- if (flag & TF_BILLBOARD) (*game).face_orientation |= GEMAT_HALO;
- else if (flag & TF_BILLBOARD2) (*game).face_orientation |= GEMAT_BILLBOARD;
- else if (flag & TF_SHADOW) (*game).face_orientation |= GEMAT_SHADOW;
-
- /* Alpha Blend */
- if (flag & TF_ALPHASORT && ELEM(alphablend, TF_ALPHA, TF_ADD)) (*game).alpha_blend = GEMAT_ALPHA_SORT;
- else if (alphablend & TF_ALPHA) (*game).alpha_blend = GEMAT_ALPHA;
- else if (alphablend & TF_ADD) (*game).alpha_blend = GEMAT_ADD;
- else if (alphablend & TF_CLIP) (*game).alpha_blend = GEMAT_CLIP;
+ Material *ma = give_current_material(ob, mat_nr + 1);
+ return ma ? ma->edit_image : NULL;
}
-/* boolean check to see if the mesh needs a material */
-static int check_tfaceneedmaterial(int flag)
+struct Image **BKE_object_material_edit_image_get_array(Object *ob)
{
- /* check if the flags we have are not deprecated != than default material options
- * also if only flags are visible and collision see if all objects using this mesh have this option in physics */
-
- /* flag is shifted in 1 to make 0 != no flag yet (see encode_tfaceflag) */
- flag -= 1;
-
- /* deprecated flags */
- flag &= ~TF_OBCOL;
- flag &= ~TF_SHAREDVERT;
- flag &= ~TF_SHAREDCOL;
-
- /* light tface flag is ignored in GLSL mode */
- flag &= ~TF_LIGHT;
-
- /* automatic detected if tex image has alpha */
- flag &= ~(TF_ALPHA << 15);
- /* automatic detected if using texture */
- flag &= ~TF_TEX;
-
- /* settings for the default NoMaterial */
- if (flag == TF_DYNAMIC)
- return 0;
-
- else
- return 1;
-}
-
-/* return number of digits of an integer */
-/* XXX to be optmized or replaced by an equivalent blender internal function */
-static int integer_getdigits(int number)
-{
- int i = 0;
- if (number == 0) return 1;
-
- while (number != 0) {
- number = (int)(number / 10);
- i++;
- }
- return i;
-}
-
-static void calculate_tface_materialname(char *matname, char *newname, int flag)
-{
- /* if flag has only light and collision and material matches those values
- * you can do strcpy(name, mat_name);
- * otherwise do: */
- int digits = integer_getdigits(flag);
- /* clamp the old name, remove the MA prefix and add the .TF.flag suffix
- * e.g. matname = "MALoooooooooooooongName"; newname = "Loooooooooooooon.TF.2" */
- BLI_snprintf(newname, MAX_ID_NAME, "%.*s.TF.%0*d", MAX_ID_NAME - (digits + 5), matname, digits, flag);
-}
-
-/* returns -1 if no match */
-static short mesh_getmaterialnumber(Mesh *me, Material *ma)
-{
- short a;
-
- for (a = 0; a < me->totcol; a++) {
- if (me->mat[a] == ma) {
- return a;
- }
- }
-
- return -1;
-}
-
-/* append material */
-static short mesh_addmaterial(Mesh *me, Material *ma)
-{
- BKE_material_append_id(G.main, &me->id, NULL);
- me->mat[me->totcol - 1] = ma;
-
- id_us_plus(&ma->id);
-
- return me->totcol - 1;
-}
-
-static void set_facetexture_flags(Material *ma, Image *image)
-{
- if (image) {
- ma->mode |= MA_FACETEXTURE;
- /* we could check if the texture has alpha, but then more meshes sharing the same
- * material may need it. Let's make it simple. */
- if (BKE_image_has_alpha(image))
- ma->mode |= MA_FACETEXTURE_ALPHA;
- }
-}
-
-/* returns material number */
-static short convert_tfacenomaterial(Main *main, Mesh *me, MTFace *tf, int flag)
-{
- Material *ma;
- char idname[MAX_ID_NAME];
- short mat_nr = -1;
-
- /* new material, the name uses the flag*/
- BLI_snprintf(idname, sizeof(idname), "MAMaterial.TF.%0*d", integer_getdigits(flag), flag);
-
- if ((ma = BLI_findstring(&main->mat, idname + 2, offsetof(ID, name) + 2))) {
- mat_nr = mesh_getmaterialnumber(me, ma);
- /* assign the material to the mesh */
- if (mat_nr == -1) mat_nr = mesh_addmaterial(me, ma);
-
- /* if needed set "Face Textures [Alpha]" Material options */
- set_facetexture_flags(ma, tf->tpage);
- }
- /* create a new material */
- else {
- ma = BKE_material_add(main, idname + 2);
-
- if (ma) {
- printf("TexFace Convert: Material \"%s\" created.\n", idname + 2);
- mat_nr = mesh_addmaterial(me, ma);
-
- /* if needed set "Face Textures [Alpha]" Material options */
- set_facetexture_flags(ma, tf->tpage);
-
- decode_tfaceflag(ma, flag, 1);
- /* the final decoding will happen after, outside the main loop
- * for now store the flag into the material and change light/tex/collision
- * store the flag as a negative number */
- ma->game.flag = -flag;
- id_us_min((ID *)ma);
- }
- else {
- printf("Error: Unable to create Material \"%s\" for Mesh \"%s\".", idname + 2, me->id.name + 2);
- }
- }
-
- /* set as converted, no need to go bad to this face */
- tf->mode |= TF_CONVERTED;
- return mat_nr;
-}
-
-/* Function to fully convert materials */
-static void convert_tfacematerial(Main *main, Material *ma)
-{
- Mesh *me;
- Material *mat_new;
- MFace *mf;
- MTFace *tf;
- int flag, index;
- int a;
- short mat_nr;
- CustomDataLayer *cdl;
- char idname[MAX_ID_NAME];
-
- for (me = main->mesh.first; me; me = me->id.next) {
- /* check if this mesh uses this material */
- for (a = 0; a < me->totcol; a++)
- if (me->mat[a] == ma) break;
-
- /* no material found */
- if (a == me->totcol) continue;
-
- /* get the active tface layer */
- index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
- cdl = (index == -1) ? NULL : &me->fdata.layers[index];
- if (!cdl) continue;
-
- /* loop over all the faces and stop at the ones that use the material*/
- for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
- if (me->mat[mf->mat_nr] != ma) continue;
-
- /* texface data for this face */
- tf = ((MTFace *)cdl->data) + a;
- flag = encode_tfaceflag(tf, 1);
-
- /* the name of the new material */
- calculate_tface_materialname(ma->id.name, (char *)&idname, flag);
-
- if ((mat_new = BLI_findstring(&main->mat, idname + 2, offsetof(ID, name) + 2))) {
- /* material already existent, see if the mesh has it */
- mat_nr = mesh_getmaterialnumber(me, mat_new);
- /* material is not in the mesh, add it */
- if (mat_nr == -1) mat_nr = mesh_addmaterial(me, mat_new);
- }
- /* create a new material */
- else {
- mat_new = BKE_material_copy(main, ma);
- if (mat_new) {
- /* rename the material*/
- BLI_strncpy(mat_new->id.name, idname, sizeof(mat_new->id.name));
- id_us_min((ID *)mat_new);
-
- mat_nr = mesh_addmaterial(me, mat_new);
- decode_tfaceflag(mat_new, flag, 1);
- }
- else {
- printf("Error: Unable to create Material \"%s\" for Mesh \"%s.", idname + 2, me->id.name + 2);
- mat_nr = mf->mat_nr;
- continue;
- }
- }
-
- /* if the material has a texture but no texture channel
- * set "Face Textures [Alpha]" Material options
- * actually we need to run it always, because of old behavior
- * of using face texture if any texture channel was present (multitex) */
- //if ((!mat_new->mtex[0]) && (!mat_new->mtex[0]->tex))
- set_facetexture_flags(mat_new, tf->tpage);
-
- /* set the material number to the face*/
- mf->mat_nr = mat_nr;
- }
- /* remove material from mesh */
- for (a = 0; a < me->totcol; ) {
- if (me->mat[a] == ma) {
- BKE_material_pop_id(main, &me->id, a, true);
- }
- else {
- a++;
- }
- }
+ Image **image_array = MEM_mallocN(sizeof(Material *) * ob->totcol, __func__);
+ for (int i = 0; i < ob->totcol; i++) {
+ image_array[i] = BKE_object_material_edit_image_get(ob, i);
}
+ return image_array;
}
-
-#define MAT_BGE_DISPUTED -99999
-
-int do_version_tface(Main *main)
+bool BKE_object_material_edit_image_set(Object *ob, short mat_nr, Image *image)
{
- Mesh *me;
- Material *ma;
- MFace *mf;
- MTFace *tf;
- CustomDataLayer *cdl;
- int a;
- int flag;
- int index;
-
- /* Operator in help menu has been removed for 2.7x */
- int fileload = 1;
-
- /* sometimes mesh has no materials but will need a new one. In those
- * cases we need to ignore the mf->mat_nr and only look at the face
- * mode because it can be zero as uninitialized or the 1st created material
- */
- int nomaterialslots;
-
- /* alert to user to check the console */
- int nowarning = 1;
-
- /* mark all the materials to conversion with a flag
- * if there is tface create a complete flag for that storing in flag
- * if there is tface and flag > 0: creates a new flag based on this face
- * if flags are different set flag to -1
- */
-
- /* 1st part: marking mesh materials to update */
- for (me = main->mesh.first; me; me = me->id.next) {
- if (ID_IS_LINKED_DATABLOCK(me)) continue;
-
- /* get the active tface layer */
- index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
- cdl = (index == -1) ? NULL : &me->fdata.layers[index];
- if (!cdl) continue;
-
- nomaterialslots = (me->totcol == 0 ? 1 : 0);
-
- /* loop over all the faces*/
- for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
- /* texface data for this face */
- tf = ((MTFace *)cdl->data) + a;
-
- /* conversion should happen only once */
- if (fileload)
- tf->mode &= ~TF_CONVERTED;
- else {
- if ((tf->mode & TF_CONVERTED)) continue;
- else tf->mode |= TF_CONVERTED;
- }
-
- /* no material slots */
- if (nomaterialslots) {
- flag = encode_tfaceflag(tf, 1);
-
- /* create/find a new material and assign to the face */
- if (check_tfaceneedmaterial(flag)) {
- mf->mat_nr = convert_tfacenomaterial(main, me, tf, flag);
- }
- /* else mark them as no-material to be reverted to 0 later */
- else {
- mf->mat_nr = -1;
- }
- }
- else if (mf->mat_nr < me->totcol) {
- ma = me->mat[mf->mat_nr];
-
- /* no material create one if necessary */
- if (!ma) {
- /* find a new material and assign to the face */
- flag = encode_tfaceflag(tf, 1);
-
- /* create/find a new material and assign to the face */
- if (check_tfaceneedmaterial(flag))
- mf->mat_nr = convert_tfacenomaterial(main, me, tf, flag);
-
- continue;
- }
-
- /* we can't read from this if it comes from a library,
- * at doversion time: direct_link might not have happened on it,
- * so ma->mtex is not pointing to valid memory yet.
- * later we could, but it's better not */
- else if (ID_IS_LINKED_DATABLOCK(ma))
- continue;
-
- /* material already marked as disputed */
- else if (ma->game.flag == MAT_BGE_DISPUTED)
- continue;
-
- /* found a material */
- else {
- flag = encode_tfaceflag(tf, ((fileload) ? 0 : 1));
-
- /* first time changing this material */
- if (ma->game.flag == 0)
- ma->game.flag = -flag;
-
- /* mark material as disputed */
- else if (ma->game.flag != -flag) {
- ma->game.flag = MAT_BGE_DISPUTED;
- continue;
- }
-
- /* material ok so far */
- else {
- ma->game.flag = -flag;
-
- /* some people uses multitexture with TexFace by creating a texture
- * channel which not necessarily the tf->tpage image. But the game engine
- * was enabling it. Now it's required to set "Face Texture [Alpha] in the
- * material settings. */
- if (!fileload)
- set_facetexture_flags(ma, tf->tpage);
- }
- }
- }
- else {
- continue;
- }
- }
-
- /* if we didn't have material slot and now we do, we need to
- * make sure the materials are correct */
- if (nomaterialslots) {
- if (me->totcol > 0) {
- for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
- if (mf->mat_nr == -1) {
- /* texface data for this face */
- tf = ((MTFace *)cdl->data) + a;
- mf->mat_nr = convert_tfacenomaterial(main, me, tf, encode_tfaceflag(tf, 1));
- }
- }
- }
- else {
- for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
- mf->mat_nr = 0;
- }
- }
- }
-
- }
-
- /* 2nd part - conversion */
- /* skip library files */
-
- /* we shouldn't loop through the materials created in the loop. make the loop stop at its original length) */
- for (ma = main->mat.first, a = 0; ma; ma = ma->id.next, a++) {
- if (ID_IS_LINKED_DATABLOCK(ma)) continue;
-
- /* disputed material */
- if (ma->game.flag == MAT_BGE_DISPUTED) {
- ma->game.flag = 0;
- if (fileload) {
- printf("Warning: material \"%s\" skipped.\n", ma->id.name + 2);
- nowarning = 0;
- }
- else {
- convert_tfacematerial(main, ma);
- }
- continue;
- }
-
- /* no conflicts in this material - 90% of cases
- * convert from tface system to material */
- else if (ma->game.flag < 0) {
- decode_tfaceflag(ma, -(ma->game.flag), 1);
-
- /* material is good make sure all faces using
- * this material are set to converted */
- if (fileload) {
- for (me = main->mesh.first; me; me = me->id.next) {
- /* check if this mesh uses this material */
- for (a = 0; a < me->totcol; a++)
- if (me->mat[a] == ma) break;
-
- /* no material found */
- if (a == me->totcol) continue;
-
- /* get the active tface layer */
- index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
- cdl = (index == -1) ? NULL : &me->fdata.layers[index];
- if (!cdl) continue;
-
- /* loop over all the faces and stop at the ones that use the material*/
- for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
- if (me->mat[mf->mat_nr] == ma) {
- /* texface data for this face */
- tf = ((MTFace *)cdl->data) + a;
- tf->mode |= TF_CONVERTED;
- }
- }
- }
- }
- }
- /* material is not used by faces with texface
- * set the default flag - do it only once */
- else {
- if (fileload) {
- ma->game.flag = GEMAT_BACKCULL;
- }
- }
+ Material *ma = give_current_material(ob, mat_nr + 1);
+ if (ma) {
+ /* both may be NULL */
+ id_us_min((ID *)ma->edit_image);
+ ma->edit_image = image;
+ id_us_plus((ID *)ma->edit_image);
+ return true;
}
-
- return nowarning;
+ return false;
}
-