= 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:
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user