Fix [#36759] UV Project - Specified UV Map doesnt work properly
authorBastien Montagne <montagne29@wanadoo.fr>
Fri, 20 Sep 2013 11:14:08 +0000 (11:14 +0000)
committerBastien Montagne <montagne29@wanadoo.fr>
Fri, 20 Sep 2013 11:14:08 +0000 (11:14 +0000)
In fact, the issue was that names of mloopuv/mtespoly layers could very easily get out of sync (a simple rename was enough), while most tools (such as the UVProject modifier) expect matching layers to have the same name!

Now matching names are check on load, and renaming of a layer through RNA is guaranted to be synchronized with its counterparts.

Thanks to Brecht & Campbell for reviews.

source/blender/blenkernel/BKE_mesh.h
source/blender/blenkernel/intern/mesh.c
source/blender/blenkernel/intern/mesh_validate.c
source/blender/makesrna/intern/rna_mesh.c

index 8b514c04a1f9c781081ccc19684770e2fad1ec64..9e80a93fd636e8f3b2b9faf90330eaaf72ee75f0 100644 (file)
@@ -119,6 +119,10 @@ struct BoundBox *BKE_mesh_boundbox_get(struct Object *ob);
 void BKE_mesh_texspace_get(struct Mesh *me, float r_loc[3], float r_rot[3], float r_size[3]);
 void BKE_mesh_texspace_copy_from_object(struct Mesh *me, struct Object *ob);
 
+bool BKE_mesh_uv_cdlayer_rename_index(struct Mesh *me, const int poly_index, const int loop_index, const int face_index,
+                                      const char *new_name, const bool do_tessface);
+bool BKE_mesh_uv_cdlayer_rename(struct Mesh *me, const char *old_name, const char *new_name, bool do_tessface);
+
 float (*BKE_mesh_vertexCos_get(struct Mesh *me, int *r_numVerts))[3];
 
 /* vertex level transformations & checks (no derived mesh) */
index 63a7b8cd982cdcf43f8fc297a2e62f4301287330..8c179d17901fa56da74d8b28df98c045c1bce8df 100644 (file)
@@ -40,6 +40,8 @@
 #include "BLI_math.h"
 #include "BLI_listbase.h"
 #include "BLI_edgehash.h"
+#include "BLI_string_utf8.h"
+#include "BLI_string.h"
 
 #include "BKE_animsys.h"
 #include "BKE_main.h"
@@ -622,6 +624,86 @@ void BKE_mesh_make_local(Mesh *me)
        }
 }
 
+bool BKE_mesh_uv_cdlayer_rename_index(Mesh *me, const int poly_index, const int loop_index, const int face_index,
+                                      const char *new_name, const bool do_tessface)
+{
+       CustomData *pdata = &me->pdata, *ldata = &me->ldata, *fdata = &me->fdata;
+       CustomDataLayer *cdlp = &pdata->layers[poly_index];
+       CustomDataLayer *cdlu = &ldata->layers[loop_index];
+       CustomDataLayer *cdlf = do_tessface ? &fdata->layers[face_index] : NULL;
+       const int step = do_tessface ? 3 : 2;
+       int i;
+
+       BLI_strncpy(cdlp->name, new_name, sizeof(cdlp->name));
+       CustomData_set_layer_unique_name(pdata, cdlp - pdata->layers);
+
+       /* Loop until we do have exactly the same name for all layers! */
+       for (i = 1; (strcmp(cdlp->name, cdlu->name) != 0 || (cdlf && strcmp(cdlp->name, cdlf->name) != 0)); i++) {
+               switch (i % step) {
+                       case 0:
+                               BLI_strncpy(cdlp->name, cdlu->name, sizeof(cdlp->name));
+                               CustomData_set_layer_unique_name(pdata, cdlp - pdata->layers);
+                               break;
+                       case 1:
+                               BLI_strncpy(cdlu->name, cdlp->name, sizeof(cdlu->name));
+                               CustomData_set_layer_unique_name(ldata, cdlu - ldata->layers);
+                               break;
+                       case 2:
+                               BLI_strncpy(cdlf->name, cdlp->name, sizeof(cdlf->name));
+                               CustomData_set_layer_unique_name(fdata, cdlf - fdata->layers);
+                               break;
+               }
+       }
+
+       return true;
+}
+
+bool BKE_mesh_uv_cdlayer_rename(Mesh *me, const char *old_name, const char *new_name, bool do_tessface)
+{
+       CustomData *pdata = &me->pdata, *ldata = &me->ldata, *fdata = &me->fdata;
+       const int pidx_start = CustomData_get_layer_index(pdata, CD_MTEXPOLY);
+       const int lidx_start = CustomData_get_layer_index(ldata, CD_MLOOPUV);
+       const int fidx_start = do_tessface ? CustomData_get_layer_index(fdata, CD_MTFACE) : -1;
+       int pidx, lidx, fidx;
+
+       do_tessface = (do_tessface && fdata->totlayer);
+       pidx = CustomData_get_named_layer(pdata, CD_MTEXPOLY, old_name);
+       lidx = CustomData_get_named_layer(ldata, CD_MLOOPUV, old_name);
+       fidx = do_tessface ? CustomData_get_named_layer(fdata, CD_MTFACE, old_name) : -1;
+
+       /* None of those cases should happen, in theory!
+        * Note this assume we have the same number of mtexpoly, mloopuv and mtface layers!
+        */
+       if (pidx == -1) {
+               if (lidx == -1) {
+                       if (fidx == -1) {
+                               /* No layer found with this name! */
+                               return false;
+                       }
+                       else {
+                               lidx = lidx_start + (fidx - fidx_start);
+                       }
+               }
+               pidx = pidx_start + (lidx - lidx_start);
+       }
+       else {
+               if (lidx == -1) {
+                       lidx = lidx_start + (pidx - pidx_start);
+               }
+               if (fidx == -1 && do_tessface) {
+                       fidx = fidx_start + (pidx - pidx_start);
+               }
+       }
+#if 0
+       /* For now, we do not consider mismatch in indices (i.e. same name leading to (relative) different indices). */
+       else if ((pidx - pidx_start) != (lidx - lidx_start)) {
+               lidx = lidx_start + (pidx - pidx_start);
+       }
+#endif
+
+       return BKE_mesh_uv_cdlayer_rename_index(me, pidx, lidx, fidx, new_name, do_tessface);
+}
+
 void BKE_mesh_boundbox_calc(Mesh *me, float r_loc[3], float r_size[3])
 {
        BoundBox *bb;
index 557d201e7fdafd9cc1c1360751236ca4ed903276..891d3080797aa17764575c1f233fb3bb51327cb9 100644 (file)
@@ -989,28 +989,37 @@ void BKE_mesh_cd_validate(Mesh *me)
 {
        int totlayer_mtex = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY);
        int totlayer_uv = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
+       int mtex_index = CustomData_get_layer_index(&me->pdata, CD_MTEXPOLY);
+       int uv_index = CustomData_get_layer_index(&me->ldata, CD_MLOOPUV);
+       int i;
 
        if (LIKELY(totlayer_mtex == totlayer_uv)) {
                /* pass */
        }
        else if (totlayer_mtex < totlayer_uv) {
-               const int uv_index_first = CustomData_get_layer_index(&me->ldata, CD_MLOOPUV);
                do {
-                       const char *from_name =  me->ldata.layers[uv_index_first + totlayer_mtex].name;
+                       const char *from_name =  me->ldata.layers[uv_index + totlayer_mtex].name;
                        CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DEFAULT, NULL, me->totpoly, from_name);
                        CustomData_set_layer_unique_name(&me->pdata, totlayer_mtex);
                } while (totlayer_uv != ++totlayer_mtex);
        }
        else if (totlayer_uv < totlayer_mtex) {
-               const int mtex_index_first = CustomData_get_layer_index(&me->pdata, CD_MTEXPOLY);
                do {
-                       const char *from_name = me->pdata.layers[mtex_index_first + totlayer_uv].name;
+                       const char *from_name = me->pdata.layers[mtex_index + totlayer_uv].name;
                        CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, me->totloop, from_name);
                        CustomData_set_layer_unique_name(&me->ldata, totlayer_uv);
                } while (totlayer_mtex != ++totlayer_uv);
        }
 
        BLI_assert(totlayer_mtex == totlayer_uv);
+
+       /* Check uv/tex names match as well!!! */
+       for (i = 0; i < totlayer_mtex; i++, mtex_index++, uv_index++) {
+               const char *name = me->pdata.layers[mtex_index].name;
+               if (strcmp(name, me->ldata.layers[uv_index].name) != 0) {
+                       BKE_mesh_uv_cdlayer_rename_index(me, mtex_index, uv_index, -1, name, false);
+               }
+       }
 }
 /** \} */
 
index 8e2d685819f703be8159b61496508a2200273cf6..fe6f33abc8c90962384a71e240e18479287af638 100644 (file)
@@ -184,18 +184,22 @@ static void rna_MeshEdgeLayer_name_set(PointerRNA *ptr, const char *value)
        rna_cd_layer_name_set(rna_mesh_edata(ptr), (CustomDataLayer *)ptr->data, value);
 }
 #endif
+#if 0
 static void rna_MeshPolyLayer_name_set(PointerRNA *ptr, const char *value)
 {
        rna_cd_layer_name_set(rna_mesh_pdata(ptr), (CustomDataLayer *)ptr->data, value);
 }
+#endif
 static void rna_MeshLoopLayer_name_set(PointerRNA *ptr, const char *value)
 {
        rna_cd_layer_name_set(rna_mesh_ldata(ptr), (CustomDataLayer *)ptr->data, value);
 }
+#if 0
 static void rna_MeshTessfaceLayer_name_set(PointerRNA *ptr, const char *value)
 {
        rna_cd_layer_name_set(rna_mesh_fdata(ptr), (CustomDataLayer *)ptr->data, value);
 }
+#endif
 /* only for layers shared between types */
 static void rna_MeshAnyLayer_name_set(PointerRNA *ptr, const char *value)
 {
@@ -684,6 +688,14 @@ static void rna_CustomDataLayer_clone_set(PointerRNA *ptr, CustomData *data, int
        CustomData_set_layer_clone_index(data, type, n);
 }
 
+/* Generic UV rename! */
+static void rna_MeshUVLayer_name_set(PointerRNA *ptr, const char *name)
+{
+       char buf[MAX_CUSTOMDATA_LAYER_NAME];
+       BLI_strncpy_utf8(buf, name, MAX_CUSTOMDATA_LAYER_NAME);
+       BKE_mesh_uv_cdlayer_rename(rna_mesh(ptr), ((CustomDataLayer *)ptr->data)->name, buf, true);
+}
+
 /* uv_layers */
 
 DEFINE_CUSTOMDATA_LAYER_COLLECTION(uv_layer, ldata, CD_MLOOPUV)
@@ -1961,7 +1973,7 @@ static void rna_def_mloopuv(BlenderRNA *brna)
 
        prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
        RNA_def_struct_name_property(srna, prop);
-       RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MeshLoopLayer_name_set");
+       RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MeshUVLayer_name_set");
        RNA_def_property_ui_text(prop, "Name", "Name of UV map");
        RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
 
@@ -1999,7 +2011,7 @@ static void rna_def_mtface(BlenderRNA *brna)
 
        prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
        RNA_def_struct_name_property(srna, prop);
-       RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MeshTessfaceLayer_name_set");
+       RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MeshUVLayer_name_set");
        RNA_def_property_ui_text(prop, "Name", "Name of UV map");
        RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
 
@@ -2111,7 +2123,7 @@ static void rna_def_mtexpoly(BlenderRNA *brna)
 
        prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
        RNA_def_struct_name_property(srna, prop);
-       RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MeshPolyLayer_name_set");
+       RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MeshUVLayer_name_set");
        RNA_def_property_ui_text(prop, "Name", "Name of UV map");
        RNA_def_property_update(prop, 0, "rna_Mesh_update_data");