= Updating the UVProject modifier to handle multiple UV layers =
authorBen Batt <benbatt@gmail.com>
Mon, 29 Jan 2007 15:10:55 +0000 (15:10 +0000)
committerBen Batt <benbatt@gmail.com>
Mon, 29 Jan 2007 15:10:55 +0000 (15:10 +0000)
* Removed the "Add UVs" option from the UVProject modifier
* Added a UV layer menu to the UVProject modifier
* Refactored the Displace modifier UV layer menu code to allow the UVProject
  modifier to share it
* Added two CustomData functions to facilitate getting layers by name

source/blender/blenkernel/BKE_customdata.h
source/blender/blenkernel/intern/customdata.c
source/blender/blenkernel/intern/modifier.c
source/blender/makesdna/DNA_modifier_types.h
source/blender/src/buttons_editing.c

index b0fe1ebde5d899268a5b7a6b5e5032ac3140c08b..ecefb6dde47c8aea49e42602ffe673ccd780cbf3 100644 (file)
@@ -113,6 +113,8 @@ int CustomData_number_of_layers(const struct CustomData *data, int type);
 /* duplicate data of a layer with flag NOFREE, and remove that flag.
  * returns the layer data */
 void *CustomData_duplicate_referenced_layer(struct CustomData *data, int type);
+void *CustomData_duplicate_referenced_layer_named(struct CustomData *data,
+                                                  int type, char *name);
 
 /* set the CD_FLAG_NOCOPY flag in custom data layers where the mask is
  * zero for the layer type, so only layer types specified by the mask
@@ -176,6 +178,8 @@ void *CustomData_em_get_n(const struct CustomData *data, void *block, int type,
  */
 void *CustomData_get_layer(const struct CustomData *data, int type);
 void *CustomData_get_layer_n(const struct CustomData *data, int type, int n);
+void *CustomData_get_layer_named(const struct CustomData *data, int type,
+                                 char *name);
 
 int CustomData_get_layer_index(const struct CustomData *data, int type);
 int CustomData_get_named_layer_index(const struct CustomData *data, int type, char *name);
index e8964ddeaf964bac1fd6a96eeff106c6fabb38da..033c1b26471d2656534ee565662f01b1e77cc191 100644 (file)
@@ -741,6 +741,26 @@ void *CustomData_duplicate_referenced_layer(struct CustomData *data, int type)
        return layer->data;
 }
 
+void *CustomData_duplicate_referenced_layer_named(struct CustomData *data,
+                                                  int type, char *name)
+{
+       CustomDataLayer *layer;
+       int layer_index;
+
+       /* get the layer index of the desired layer */
+       layer_index = CustomData_get_named_layer_index(data, type, name);
+       if(layer_index < 0) return NULL;
+
+       layer = &data->layers[layer_index];
+
+       if (layer->flag & CD_FLAG_NOFREE) {
+               layer->data = MEM_dupallocN(layer->data);
+               layer->flag &= ~CD_FLAG_NOFREE;
+       }
+
+       return layer->data;
+}
+
 void CustomData_free_temporary(CustomData *data, int totelem)
 {
        CustomDataLayer *layer;
@@ -953,6 +973,15 @@ void *CustomData_get_layer_n(const CustomData *data, int type, int n)
        return data->layers[layer_index+n].data;
 }
 
+void *CustomData_get_layer_named(const struct CustomData *data, int type,
+                                 char *name)
+{
+       int layer_index = CustomData_get_named_layer_index(data, type, name);
+       if(layer_index < 0) return NULL;
+
+       return data->layers[layer_index].data;
+}
+
 void *CustomData_set_layer(const CustomData *data, int type, void *ptr)
 {
        /* get the layer index of the first layer of type */
index 7eb3a141513ed74f49ed0eabdd2931433e1a6ae0..4894a238634080a8b33e0f53a0f2b671fa537559 100644 (file)
@@ -2279,6 +2279,23 @@ static void displaceModifier_updateDepgraph(
        }
 }
 
+static void validate_layer_name(const CustomData *data, int type, char *name)
+{
+       int index = -1;
+
+       /* if a layer name was given, try to find that layer */
+       if(name[0])
+               index = CustomData_get_named_layer_index(data, CD_MTFACE, name);
+
+       if(index < 0) {
+               /* either no layer was specified, or the layer we want has been
+                * deleted, so assign the active layer to name
+                */
+               index = CustomData_get_active_layer_index(data, CD_MTFACE);
+               strcpy(name, data->layers[index].name);
+       }
+}
+
 static void get_texture_coords(DisplaceModifierData *dmd, Object *ob,
                                DerivedMesh *dm,
                                float (*co)[3], float (*texco)[3],
@@ -2301,27 +2318,14 @@ static void get_texture_coords(DisplaceModifierData *dmd, Object *ob,
                        MFace *mf;
                        char *done = MEM_callocN(sizeof(*done) * numVerts,
                                                 "get_texture_coords done");
-                       MTFace *tf = NULL;
-                       int numFaces = dm->getNumFaces(dm), itf;
-                       
-                       if (dmd->uvlayer_name[0]) {
-                               itf = CustomData_get_named_layer_index(&dm->faceData, CD_MTFACE, dmd->uvlayer_name);
-                               if (itf != -1)
-                                       tf = dm->faceData.layers[itf].data;
-                               else {
-                                       /*looks like the layer we want has been deleted, so assign the 
-                                         first layer to dmd.*/
-                                       itf = CustomData_get_active_layer_index(&dm->faceData, CD_MTFACE);
-                                       tf = dm->faceData.layers[itf].data;
-                                       strcpy(dmd->uvlayer_name, dm->faceData.layers[itf].name);
-                               }
-                       } else {
-                               /* no uv layer specified, use the active one */
-                               itf = CustomData_get_active_layer_index(&dm->faceData, CD_MTFACE);
-                               tf = dm->faceData.layers[itf].data;
-                               strcpy(dmd->uvlayer_name, dm->faceData.layers[itf].name);
-                       }
-                       
+                       int numFaces = dm->getNumFaces(dm);
+                       MTFace *tf;
+
+                       validate_layer_name(&dm->faceData, CD_MTFACE, dmd->uvlayer_name);
+
+                       tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE,
+                                                       dmd->uvlayer_name);
+
                        /* verts are given the UV from the first face that uses them */
                        for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tf) {
                                if(!done[mf->v1]) {
@@ -2531,7 +2535,7 @@ static void uvprojectModifier_initData(ModifierData *md)
        for(i = 0; i < MOD_UVPROJECT_MAXPROJECTORS; ++i)
                umd->projectors[i] = NULL;
        umd->image = NULL;
-       umd->flags = MOD_UVPROJECT_ADDUVS;
+       umd->flags = 0;
        umd->num_projectors = 1;
        umd->aspectx = umd->aspecty = 1.0f;
 }
@@ -2624,22 +2628,18 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd,
                if(umd->projectors[i])
                        projectors[num_projectors++].ob = umd->projectors[i];
 
-       tface = dm->getFaceDataArray(dm, CD_MTFACE);
-
        if(num_projectors == 0) return dm;
 
-       if(!tface) {
-               if(!(umd->flags & MOD_UVPROJECT_ADDUVS)) return dm;
+       /* make sure there are UV layers available */
+       if(!dm->getFaceDataArray(dm, CD_MTFACE)) return dm;
 
-               DM_add_face_layer(dm, CD_MTFACE, CD_CALLOC, NULL);
-               tface = dm->getFaceDataArray(dm, CD_MTFACE);
-               new_tfaces = 1;
-       }
-       else {
-               /* make sure we are not modifying the original layer */
-               CustomData_duplicate_referenced_layer(&dm->faceData, CD_MTFACE);
-               tface = dm->getFaceDataArray(dm, CD_MTFACE);
-       }
+       /* make sure we're using an existing layer */
+       validate_layer_name(&dm->faceData, CD_MTFACE, umd->uvlayer_name);
+
+       /* make sure we are not modifying the original UV layer */
+       tface = CustomData_duplicate_referenced_layer_named(&dm->faceData,
+                                                           CD_MTFACE,
+                                                           umd->uvlayer_name);
 
        numVerts = dm->getNumVerts(dm);
 
index cb4ac1e837fa7a7a5fe4ccbce9bd0c38638efe59..704c54afcd5e493cb5c3494e62718ac13840c53f 100644 (file)
@@ -208,13 +208,12 @@ typedef struct UVProjectModifierData {
        int flags;
        int num_projectors;
        float aspectx, aspecty;
+       char uvlayer_name[32];
+       int uvlayer_tmp, pad;
 } UVProjectModifierData;
 
 #define MOD_UVPROJECT_MAXPROJECTORS 10
 
-/* UVProjectModifierData->flags */
-#define MOD_UVPROJECT_ADDUVS 1<<0
-
 typedef struct DecimateModifierData {
        ModifierData modifier;
 
index 0591b71d4ee9ad16755cf5ddf91b2c6527fe523f..23580dd78ad811ae756c0586d3f10b8d85acba32 100644 (file)
@@ -1380,6 +1380,51 @@ static void modifiers_convertToReal(void *ob_v, void *md_v)
        BIF_undo_push("Modifier convert to real");
 }
 
+static void build_uvlayer_menu_vars(CustomData *data, char **menu_string,
+                                    int *uvlayer_tmp, char *uvlayer_name)
+{
+       char strtmp[38];
+       int totuv, i;
+       CustomDataLayer *layer
+                   = &data->layers[CustomData_get_layer_index(data, CD_MTFACE)];
+
+       *uvlayer_tmp = -1;
+
+       totuv = CustomData_number_of_layers(data, CD_MTFACE);
+
+       *menu_string = MEM_callocN(sizeof(**menu_string) * (totuv * 38 + 10),
+                                  "menu_string");
+       sprintf(*menu_string, "UV Layer%%t");
+       for(i = 0; i < totuv; i++) {
+               /* assign first layer as uvlayer_name if uvlayer_name is null. */
+               if(strcmp(layer->name, uvlayer_name) == 0) *uvlayer_tmp = i + 1;
+               sprintf(strtmp, "|%s%%x%d", layer->name, i + 1);
+               strcat(*menu_string, strtmp);
+               layer++;
+       }
+
+       /* there is no uvlayer defined, or else it was deleted. Assign active
+        * layer, then recalc modifiers.
+        */
+       if(*uvlayer_tmp == -1) {
+               if(CustomData_get_active_layer_index(data, CD_MTFACE) != -1) {
+                       *uvlayer_tmp = 1;
+                       layer = data->layers;
+                       for(i = 0; i < CustomData_get_active_layer_index(data, CD_MTFACE);
+                           i++, layer++) {
+                               if(layer->type == CD_MTFACE) (*uvlayer_tmp)++;
+                       }
+                       strcpy(uvlayer_name, layer->name);
+
+                       /* update the modifiers */
+                       do_modifier_panels(B_MODIFIER_RECALC);
+               } else {
+                       /* ok we have no uv layers, so make sure menu button knows that.*/
+                       *uvlayer_tmp = 0;
+               }
+       }
+}
+
 void set_displace_uvlayer(void *arg1, void *arg2)
 {
        DisplaceModifierData *dmd=arg1;
@@ -1392,6 +1437,18 @@ void set_displace_uvlayer(void *arg1, void *arg2)
        strcpy(dmd->uvlayer_name, layer->name);
 }
 
+void set_uvproject_uvlayer(void *arg1, void *arg2)
+{
+       UVProjectModifierData *umd=arg1;
+       CustomDataLayer *layer = arg2;
+
+       /*check we have UV layers*/
+       if (umd->uvlayer_tmp < 1) return;
+       layer = layer + (umd->uvlayer_tmp-1);
+       
+       strcpy(umd->uvlayer_name, layer->name);
+}
+
 static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco, int *yco, int index, int cageIndex, int lastCageIndex)
 {
        ModifierTypeInfo *mti = modifierType_getInfo(md->type);
@@ -1498,9 +1555,11 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
                } else if (md->type==eModifierType_Displace) {
                        DisplaceModifierData *dmd = (DisplaceModifierData *)md;
                        height = 124;
-                       if(dmd->texmapping == MOD_DISP_MAP_OBJECT || dmd->texmapping == MOD_DISP_MAP_UV) height += 19;
+                       if(dmd->texmapping == MOD_DISP_MAP_OBJECT ||
+                          dmd->texmapping == MOD_DISP_MAP_UV)
+                               height += 19;
                } else if (md->type==eModifierType_UVProject) {
-                       height = 86 + ((UVProjectModifierData *)md)->num_projectors * 19;
+                       height = 105 + ((UVProjectModifierData *)md)->num_projectors * 19;
                } else if (md->type==eModifierType_Decimate) {
                        height = 48;
                } else if (md->type==eModifierType_Wave) {
@@ -1641,47 +1700,19 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
                                  0.0, 1.0, 0, 0,
                                  "Texture coordinates used for displacement input");
                        if (dmd->texmapping == MOD_DISP_MAP_UV) {
-                               char strtmp[1024], strtmp2[38];
-                               int totuv, i;
-                               CustomData *fdata = G.obedit?&G.editMesh->fdata:&((Mesh*)ob->data)->fdata;
-                               CustomDataLayer *layer = &fdata->layers[CustomData_get_layer_index(fdata, CD_MTFACE)];
-                               
-                               dmd->uvlayer_tmp = -1;
-                               
-                               totuv=CustomData_number_of_layers(fdata, CD_MTFACE);
-                               sprintf(strtmp, "UV Layer%%t");
-                               for (i=0; i<totuv; i++) {
-                                       /*assign first layer as uvlayer_name if uvlayer_name is null.*/
-                                       if (strcmp(layer->name, dmd->uvlayer_name)==0) dmd->uvlayer_tmp = i+1;
-                                       sprintf(strtmp2, "|%s%%x%d", layer->name, i+1);
-                                       strcat(strtmp, strtmp2);
-                                       layer++;
-                               }
-                               
-                               /*there is no uvlayer defined, or else it was deleted.  Assign active layer,
-                                 then recalc modifiers.*/
-                               if (dmd->uvlayer_tmp == -1) {
-                                       if (CustomData_get_active_layer_index(fdata, CD_MTFACE) != -1) {
-                                               dmd->uvlayer_tmp = 1;                                   
-                                               layer = fdata->layers;
-                                               for (i=0; i<CustomData_get_active_layer_index(fdata, CD_MTFACE); i++, layer++) {
-                                                       if (layer->type==CD_MTFACE) dmd->uvlayer_tmp++;
-                                               }
-                                               strcpy(dmd->uvlayer_name, layer->name);
-                                               
-                                               /*update the modifiers*/
-                                               do_modifier_panels(B_MODIFIER_RECALC);
-                                       } else {
-                                               /* ok we have no uv layers, so make sure menu button knows that.*/
-                                               dmd->uvlayer_tmp = 0;
-                                       }
-                               }
-                               
+                               char *strtmp;
+                               int i;
+                               CustomData *fdata = G.obedit ? &G.editMesh->fdata
+                                                            : &((Mesh*)ob->data)->fdata;
+                               build_uvlayer_menu_vars(fdata, &strtmp, &dmd->uvlayer_tmp,
+                                                       dmd->uvlayer_name);
                                but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
-                                 lx, (cy -= 19), buttonWidth, 19, &dmd->uvlayer_tmp,
-                                 0.0, 1.0, 0, 0, "Set the UV layer to use");
-                               
-                               uiButSetFunc(but, set_displace_uvlayer, dmd, &fdata->layers[CustomData_get_layer_index(fdata, CD_MTFACE)]);
+                                     lx, (cy -= 19), buttonWidth, 19, &dmd->uvlayer_tmp,
+                                     0.0, 1.0, 0, 0, "Set the UV layer to use");
+                               MEM_freeN(strtmp);
+                               i = CustomData_get_layer_index(fdata, CD_MTFACE);
+                               uiButSetFunc(but, set_displace_uvlayer, dmd,
+                                            &fdata->layers[i]);
                        }
                        if(dmd->texmapping == MOD_DISP_MAP_OBJECT) {
                                uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
@@ -1692,11 +1723,17 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
                } else if (md->type==eModifierType_UVProject) {
                        UVProjectModifierData *umd = (UVProjectModifierData *) md;
                        int i;
-                       uiDefButBitI(block, TOG, MOD_UVPROJECT_ADDUVS,
-                                    B_MODIFIER_RECALC, "Add UVs",
-                                    lx, (cy-=19), buttonWidth, 19,
-                                    &umd->flags, 0, 0, 0, 0,
-                                    "Add UV coordinates if missing");
+                       char *strtmp;
+                       CustomData *fdata = G.obedit ? &G.editMesh->fdata
+                                                    : &((Mesh*)ob->data)->fdata;
+                       build_uvlayer_menu_vars(fdata, &strtmp, &umd->uvlayer_tmp,
+                                               umd->uvlayer_name);
+                       but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
+                             lx, (cy -= 19), buttonWidth, 19, &umd->uvlayer_tmp,
+                             0.0, 1.0, 0, 0, "Set the UV layer to use");
+                       i = CustomData_get_layer_index(fdata, CD_MTFACE);
+                       uiButSetFunc(but, set_uvproject_uvlayer, umd, &fdata->layers[i]);
+                       MEM_freeN(strtmp);
                        uiDefButF(block, NUM, B_MODIFIER_RECALC, "AspX:",
                                  lx, (cy -= 19), buttonWidth / 2, 19, &umd->aspectx,
                                  1, 1000, 100, 2,