= Updating the UVProject modifier to handle multiple UV layers =

* 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
This commit is contained in:
2007-01-29 15:10:55 +00:00
parent 2d361fca0d
commit 2a47217cba
5 changed files with 154 additions and 85 deletions

View 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);

View 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 */

View 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);

View 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;

View 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,