vertex group mirror
- now works in vertex select + weight paint mode. - added option not to mirror all vertex groups.
This commit is contained in:
@@ -1086,6 +1086,7 @@ class VIEW3D_MT_paint_weight(Menu):
|
||||
|
||||
layout.operator("object.vertex_group_normalize_all", text="Normalize All")
|
||||
layout.operator("object.vertex_group_normalize", text="Normalize")
|
||||
layout.operator("object.vertex_group_mirror", text="Mirror")
|
||||
layout.operator("object.vertex_group_invert", text="Invert")
|
||||
layout.operator("object.vertex_group_clean", text="Clean")
|
||||
layout.operator("object.vertex_group_levels", text="Levels")
|
||||
|
@@ -1036,6 +1036,7 @@ class VIEW3D_PT_tools_weightpaint(View3DPanel, Panel):
|
||||
col.active = ob.vertex_groups.active is not None
|
||||
col.operator("object.vertex_group_normalize_all", text="Normalize All")
|
||||
col.operator("object.vertex_group_normalize", text="Normalize")
|
||||
col.operator("object.vertex_group_mirror", text="Mirror")
|
||||
col.operator("object.vertex_group_invert", text="Invert")
|
||||
col.operator("object.vertex_group_clean", text="Clean")
|
||||
col.operator("object.vertex_group_levels", text="Levels")
|
||||
|
@@ -45,6 +45,7 @@ struct bDeformGroup *defgroup_duplicate(struct bDeformGroup *ingroup);
|
||||
struct bDeformGroup *defgroup_find_name(struct Object *ob, const char *name);
|
||||
int defgroup_find_index(struct Object *ob, struct bDeformGroup *dg);
|
||||
int *defgroup_flip_map(struct Object *ob, int *flip_map_len, int use_default);
|
||||
int *defgroup_flip_map_single(struct Object *ob, int *flip_map_len, int use_default, int defgroup);
|
||||
int defgroup_flip_index(struct Object *ob, int index, int use_default);
|
||||
int defgroup_name_index(struct Object *ob, const char *name);
|
||||
void defgroup_unique_name(struct bDeformGroup *dg, struct Object *ob);
|
||||
|
@@ -257,17 +257,19 @@ int defgroup_find_index (Object *ob, bDeformGroup *dg)
|
||||
/* note, must be freed */
|
||||
int *defgroup_flip_map(Object *ob, int *flip_map_len, int use_default)
|
||||
{
|
||||
bDeformGroup *dg;
|
||||
int totdg= *flip_map_len= BLI_countlist(&ob->defbase);
|
||||
|
||||
if(totdg==0) {
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
bDeformGroup *dg;
|
||||
char name[sizeof(dg->name)];
|
||||
int i, flip_num, *map= MEM_mallocN(totdg * sizeof(int), __func__);
|
||||
|
||||
memset(map, -1, totdg * sizeof(int));
|
||||
for (i=0; i < totdg; i++) {
|
||||
map[i]= -1;
|
||||
}
|
||||
|
||||
for (dg=ob->defbase.first, i=0; dg; dg=dg->next, i++) {
|
||||
if(map[i] == -1) { /* may be calculated previously */
|
||||
@@ -276,7 +278,7 @@ int *defgroup_flip_map(Object *ob, int *flip_map_len, int use_default)
|
||||
if(use_default)
|
||||
map[i]= i;
|
||||
|
||||
flip_side_name(name, dg->name, 0);
|
||||
flip_side_name(name, dg->name, FALSE);
|
||||
if(strcmp(name, dg->name)) {
|
||||
flip_num= defgroup_name_index(ob, name);
|
||||
if(flip_num >= 0) {
|
||||
@@ -290,6 +292,40 @@ int *defgroup_flip_map(Object *ob, int *flip_map_len, int use_default)
|
||||
}
|
||||
}
|
||||
|
||||
/* note, must be freed */
|
||||
int *defgroup_flip_map_single(Object *ob, int *flip_map_len, int use_default, int defgroup)
|
||||
{
|
||||
int totdg= *flip_map_len= BLI_countlist(&ob->defbase);
|
||||
|
||||
if(totdg==0) {
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
bDeformGroup *dg;
|
||||
char name[sizeof(dg->name)];
|
||||
int i, flip_num, *map= MEM_mallocN(totdg * sizeof(int), __func__);
|
||||
|
||||
for (i=0; i < totdg; i++) {
|
||||
if (use_default) map[i]= i;
|
||||
else map[i]= -1;
|
||||
}
|
||||
|
||||
dg= BLI_findlink(&ob->defbase, defgroup);
|
||||
|
||||
flip_side_name(name, dg->name, FALSE);
|
||||
if(strcmp(name, dg->name)) {
|
||||
flip_num= defgroup_name_index(ob, name);
|
||||
|
||||
if(flip_num >= 0) {
|
||||
map[defgroup]= flip_num;
|
||||
map[flip_num]= defgroup;
|
||||
}
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
int defgroup_flip_index(Object *ob, int index, int use_default)
|
||||
{
|
||||
bDeformGroup *dg= BLI_findlink(&ob->defbase, index);
|
||||
|
@@ -209,7 +209,7 @@ void ED_vgroup_select_by_name(struct Object *ob, const char *name);
|
||||
int ED_vgroup_data_create(struct ID *id);
|
||||
int ED_vgroup_give_array(struct ID *id, struct MDeformVert **dvert_arr, int *dvert_tot);
|
||||
int ED_vgroup_copy_array(struct Object *ob, struct Object *ob_from);
|
||||
void ED_vgroup_mirror(struct Object *ob, const short mirror_weights, const short flip_vgroups);
|
||||
void ED_vgroup_mirror(struct Object *ob, const short mirror_weights, const short flip_vgroups, const short all_vgroups);
|
||||
|
||||
int ED_vgroup_object_is_edit_mode(struct Object *ob);
|
||||
|
||||
|
@@ -1527,14 +1527,32 @@ static void vgroup_clean_all(Object *ob, float eul, int keep_single)
|
||||
static void dvert_mirror_op(MDeformVert *dvert, MDeformVert *dvert_mirr,
|
||||
const char sel, const char sel_mirr,
|
||||
const int *flip_map, const int flip_map_len,
|
||||
const short mirror_weights, const short flip_vgroups)
|
||||
const short mirror_weights, const short flip_vgroups,
|
||||
const short all_vgroups, const int act_vgroup)
|
||||
{
|
||||
BLI_assert(sel || sel_mirr);
|
||||
|
||||
if(sel_mirr && sel) {
|
||||
/* swap */
|
||||
if(mirror_weights)
|
||||
SWAP(MDeformVert, *dvert, *dvert_mirr);
|
||||
if(mirror_weights) {
|
||||
if (all_vgroups) {
|
||||
SWAP(MDeformVert, *dvert, *dvert_mirr);
|
||||
}
|
||||
else {
|
||||
MDeformWeight *dw= defvert_find_index(dvert, act_vgroup);
|
||||
MDeformWeight *dw_mirr= defvert_find_index(dvert_mirr, act_vgroup);
|
||||
|
||||
if (dw || dw_mirr) {
|
||||
if (dw_mirr == NULL)
|
||||
dw_mirr= defvert_verify_index(dvert_mirr, act_vgroup);
|
||||
if (dw == NULL)
|
||||
dw= defvert_verify_index(dvert, act_vgroup);
|
||||
|
||||
SWAP(float, dw->weight, dw_mirr->weight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(flip_vgroups) {
|
||||
defvert_flip(dvert, flip_map, flip_map_len);
|
||||
defvert_flip(dvert_mirr, flip_map, flip_map_len);
|
||||
@@ -1554,52 +1572,109 @@ static void dvert_mirror_op(MDeformVert *dvert, MDeformVert *dvert_mirr,
|
||||
}
|
||||
}
|
||||
|
||||
void ED_vgroup_mirror(Object *ob, const short mirror_weights, const short flip_vgroups)
|
||||
/* TODO, vgroup locking */
|
||||
/* TODO, face masking */
|
||||
void ED_vgroup_mirror(Object *ob, const short mirror_weights, const short flip_vgroups, const short all_vgroups)
|
||||
{
|
||||
#define VGROUP_MIRR_OP dvert_mirror_op(dvert, dvert_mirr, sel, sel_mirr, flip_map, flip_map_len, mirror_weights, flip_vgroups)
|
||||
|
||||
#define VGROUP_MIRR_OP \
|
||||
dvert_mirror_op(dvert, dvert_mirr, \
|
||||
sel, sel_mirr, \
|
||||
flip_map, flip_map_len, \
|
||||
mirror_weights, flip_vgroups, \
|
||||
all_vgroups, act_vgroup \
|
||||
)
|
||||
|
||||
EditVert *eve, *eve_mirr;
|
||||
MDeformVert *dvert, *dvert_mirr;
|
||||
short sel, sel_mirr;
|
||||
int *flip_map, flip_map_len;
|
||||
const int act_vgroup= ob->actdef > 0 ? ob->actdef-1 : 0;
|
||||
|
||||
if(mirror_weights==0 && flip_vgroups==0)
|
||||
return;
|
||||
|
||||
flip_map= defgroup_flip_map(ob, &flip_map_len, FALSE);
|
||||
flip_map= all_vgroups ?
|
||||
defgroup_flip_map(ob, &flip_map_len, FALSE) :
|
||||
defgroup_flip_map_single(ob, &flip_map_len, FALSE, act_vgroup);
|
||||
|
||||
/* only the active group */
|
||||
if(ob->type == OB_MESH) {
|
||||
Mesh *me= ob->data;
|
||||
EditMesh *em = BKE_mesh_get_editmesh(me);
|
||||
|
||||
if (em) {
|
||||
if(!CustomData_has_layer(&em->vdata, CD_MDEFORMVERT)) {
|
||||
MEM_freeN(flip_map);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!CustomData_has_layer(&em->vdata, CD_MDEFORMVERT)) {
|
||||
MEM_freeN(flip_map);
|
||||
return;
|
||||
EM_cache_x_mirror_vert(ob, em);
|
||||
|
||||
/* Go through the list of editverts and assign them */
|
||||
for(eve=em->verts.first; eve; eve=eve->next){
|
||||
if((eve_mirr=eve->tmp.v)) {
|
||||
sel= eve->f & SELECT;
|
||||
sel_mirr= eve_mirr->f & SELECT;
|
||||
|
||||
if((sel || sel_mirr) && (eve != eve_mirr)) {
|
||||
dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
|
||||
dvert_mirr= CustomData_em_get(&em->vdata, eve_mirr->data, CD_MDEFORMVERT);
|
||||
if(dvert && dvert_mirr) {
|
||||
VGROUP_MIRR_OP;
|
||||
}
|
||||
}
|
||||
|
||||
eve->tmp.v= eve_mirr->tmp.v= NULL;
|
||||
}
|
||||
}
|
||||
|
||||
BKE_mesh_end_editmesh(me, em);
|
||||
}
|
||||
else {
|
||||
/* object mode / weight paint */
|
||||
MVert *mv, *mv_mirr;
|
||||
int vidx, vidx_mirr;
|
||||
const int use_vert_sel= (me->editflag & ME_EDIT_VERT_SEL) != 0;
|
||||
|
||||
EM_cache_x_mirror_vert(ob, em);
|
||||
if (me->dvert == NULL) {
|
||||
MEM_freeN(flip_map);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Go through the list of editverts and assign them */
|
||||
for(eve=em->verts.first; eve; eve=eve->next){
|
||||
if((eve_mirr=eve->tmp.v)) {
|
||||
sel= eve->f & SELECT;
|
||||
sel_mirr= eve_mirr->f & SELECT;
|
||||
if (!use_vert_sel) {
|
||||
sel= sel_mirr= TRUE;
|
||||
}
|
||||
|
||||
/* tag verts we have used */
|
||||
for(vidx= 0, mv= me->mvert; vidx < me->totvert; vidx++, mv++) {
|
||||
mv->flag &= ~ME_VERT_TMP_TAG;
|
||||
}
|
||||
|
||||
for(vidx= 0, mv= me->mvert; vidx < me->totvert; vidx++, mv++) {
|
||||
if ( ((mv->flag & ME_VERT_TMP_TAG) == 0) &&
|
||||
((vidx_mirr= mesh_get_x_mirror_vert(ob, vidx)) != -1) &&
|
||||
(vidx != vidx_mirr) &&
|
||||
((((mv_mirr= me->mvert + vidx_mirr)->flag) & ME_VERT_TMP_TAG) == 0))
|
||||
{
|
||||
|
||||
if (use_vert_sel) {
|
||||
sel= mv->flag & SELECT;
|
||||
sel_mirr= mv_mirr->flag & SELECT;
|
||||
}
|
||||
|
||||
if (sel || sel_mirr) {
|
||||
dvert= &me->dvert[vidx];
|
||||
dvert_mirr= &me->dvert[vidx_mirr];
|
||||
|
||||
if((sel || sel_mirr) && (eve != eve_mirr)) {
|
||||
dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
|
||||
dvert_mirr= CustomData_em_get(&em->vdata, eve_mirr->data, CD_MDEFORMVERT);
|
||||
if(dvert && dvert_mirr) {
|
||||
VGROUP_MIRR_OP;
|
||||
}
|
||||
}
|
||||
|
||||
eve->tmp.v= eve_mirr->tmp.v= NULL;
|
||||
mv->flag |= ME_VERT_TMP_TAG;
|
||||
mv_mirr->flag |= ME_VERT_TMP_TAG;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BKE_mesh_end_editmesh(me, em);
|
||||
}
|
||||
else if (ob->type == OB_LATTICE) {
|
||||
Lattice *lt= ob->data;
|
||||
@@ -2508,7 +2583,10 @@ static int vertex_group_mirror_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
|
||||
|
||||
ED_vgroup_mirror(ob, RNA_boolean_get(op->ptr,"mirror_weights"), RNA_boolean_get(op->ptr,"flip_group_names"));
|
||||
ED_vgroup_mirror(ob,
|
||||
RNA_boolean_get(op->ptr,"mirror_weights"),
|
||||
RNA_boolean_get(op->ptr,"flip_group_names"),
|
||||
RNA_boolean_get(op->ptr,"all_groups"));
|
||||
|
||||
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
||||
WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
|
||||
@@ -2526,7 +2604,7 @@ void OBJECT_OT_vertex_group_mirror(wmOperatorType *ot)
|
||||
"flipping when both sides are selected otherwise copy from unselected";
|
||||
|
||||
/* api callbacks */
|
||||
ot->poll= vertex_group_poll_edit;
|
||||
ot->poll= vertex_group_poll;
|
||||
ot->exec= vertex_group_mirror_exec;
|
||||
|
||||
/* flags */
|
||||
@@ -2535,6 +2613,7 @@ void OBJECT_OT_vertex_group_mirror(wmOperatorType *ot)
|
||||
/* properties */
|
||||
RNA_def_boolean(ot->srna, "mirror_weights", TRUE, "Mirror Weights", "Mirror weights");
|
||||
RNA_def_boolean(ot->srna, "flip_group_names", TRUE, "Flip Groups", "Flip vertex group names");
|
||||
RNA_def_boolean(ot->srna, "all_groups", FALSE, "All Groups", "Mirror all vertex groups weights");
|
||||
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user