Fix #35551: the topology mirror setting affected shape key and vertex group but

this was confusing as there was no setting visible for it. Now these menus
contain an entry to mirror without and with topology mirror.
This commit is contained in:
Brecht Van Lommel 2013-06-28 17:13:09 +00:00
parent e5ff9cced4
commit 77e0709e48
13 changed files with 71 additions and 43 deletions

@ -34,6 +34,7 @@ class MESH_MT_vertex_group_specials(Menu):
layout.operator("object.vertex_group_copy_to_linked", icon='LINK_AREA')
layout.operator("object.vertex_group_copy_to_selected", icon='LINK_AREA')
layout.operator("object.vertex_group_mirror", icon='ARROW_LEFTRIGHT')
layout.operator("object.vertex_group_mirror", text="Mirror Vertex Group (Topology)", icon='ARROW_LEFTRIGHT').use_topology = True
layout.operator("object.vertex_group_remove_from", icon='X', text="Remove from All Groups").use_all_groups = True
layout.operator("object.vertex_group_remove_from", icon='X', text="Clear Active Group").use_all_verts = True
layout.operator("object.vertex_group_remove", icon='X', text="Delete All Groups").all = True
@ -53,6 +54,7 @@ class MESH_MT_shape_key_specials(Menu):
layout.operator("object.shape_key_transfer", icon='COPY_ID') # icon is not ideal
layout.operator("object.join_shapes", icon='COPY_ID') # icon is not ideal
layout.operator("object.shape_key_mirror", icon='ARROW_LEFTRIGHT')
layout.operator("object.shape_key_mirror", text="Mirror Shape Key (Topology)", icon='ARROW_LEFTRIGHT').use_topology = True
layout.operator("object.shape_key_add", icon='ZOOMIN', text="New Shape From Mix").from_mix = True
layout.operator("object.shape_key_remove", icon='X', text="Delete All Shapes").all = True

@ -1153,7 +1153,9 @@ class VIEW3D_PT_tools_weightpaint_options(Panel, View3DPaintPanel):
if obj.type == 'MESH':
mesh = obj.data
col.prop(mesh, "use_mirror_x")
col.prop(mesh, "use_mirror_topology")
row = col.row()
row.active = mesh.use_mirror_x
row.prop(mesh, "use_mirror_topology")
col.prop(wpaint, "input_samples")

@ -199,10 +199,11 @@ static void envelope_bone_weighting(Object *ob, Mesh *mesh, float (*verts)[3], i
bDeformGroup *dgroup;
float distance;
int i, iflip, j;
bool use_topology = (mesh->editflag & ME_EDIT_MIRROR_TOPO) != 0;
/* for each vertex in the mesh */
for (i = 0; i < mesh->totvert; i++) {
iflip = (dgroupflip) ? mesh_get_x_mirror_vert(ob, i) : 0;
iflip = (dgroupflip) ? mesh_get_x_mirror_vert(ob, i, use_topology) : 0;
/* for each skinnable bone */
for (j = 0; j < numbones; ++j) {

@ -652,6 +652,7 @@ void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numsource,
float solution, weight;
int *vertsflipped = NULL, *mask = NULL;
int a, tottri, j, bbone, firstsegment, lastsegment;
bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
MVert *mvert = me->mvert;
int use_vert_sel = FALSE;
@ -716,7 +717,7 @@ void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numsource,
if (dgroupflip) {
vertsflipped = MEM_callocN(sizeof(int) * me->totvert, "vertsflipped");
for (a = 0; a < me->totvert; a++)
vertsflipped[a] = mesh_get_x_mirror_vert(ob, a);
vertsflipped[a] = mesh_get_x_mirror_vert(ob, a, use_topology);
}
/* compute weights per bone */

@ -77,9 +77,9 @@ struct MeshStatVis;
/* editmesh_utils.c */
void EDBM_verts_mirror_cache_begin_ex(struct BMEditMesh *em, const int axis,
const bool use_self, const bool use_select,
const bool is_topo, float maxdist, int *r_index);
const bool use_topology, float maxdist, int *r_index);
void EDBM_verts_mirror_cache_begin(struct BMEditMesh *em, const int axis,
const bool use_self, const bool use_select);
const bool use_self, const bool use_select, const bool use_toplogy);
void EDBM_verts_mirror_apply(struct BMEditMesh *em, const int sel_from, const int sel_to);
struct BMVert *EDBM_verts_mirror_get(struct BMEditMesh *em, struct BMVert *v);
void EDBM_verts_mirror_cache_clear(struct BMEditMesh *em, struct BMVert *v);
@ -241,7 +241,8 @@ void ED_vgroup_data_clamp_range(struct ID *id, const int total);
bool ED_vgroup_give_array(struct ID *id, struct MDeformVert **dvert_arr, int *dvert_tot);
bool ED_vgroup_copy_array(struct Object *ob, struct Object *ob_from);
void ED_vgroup_mirror(struct Object *ob,
const bool mirror_weights, const bool flip_vgroups, const bool all_vgroups,
const bool mirror_weights, const bool flip_vgroups,
const bool all_vgroups, const bool use_topology,
int *r_totmirr, int *r_totfail);
bool ED_vgroup_object_is_edit_mode(struct Object *ob);
@ -304,8 +305,10 @@ int mesh_mirrtopo_table(struct Object *ob, char mode);
/* retrieves mirrored cache vert, or NULL if there isn't one.
* note: calling this without ensuring the mirror cache state
* is bad.*/
int mesh_get_x_mirror_vert(struct Object *ob, int index);
struct BMVert *editbmesh_get_x_mirror_vert(struct Object *ob, struct BMEditMesh *em, struct BMVert *eve, const float co[3], int index);
int mesh_get_x_mirror_vert(struct Object *ob, int index, const bool use_topology);
struct BMVert *editbmesh_get_x_mirror_vert(struct Object *ob, struct BMEditMesh *em,
struct BMVert *eve, const float co[3],
int index, const bool use_topology);
int *mesh_get_x_mirror_faces(struct Object *ob, struct BMEditMesh *em);
bool ED_mesh_pick_vert(struct bContext *C, struct Object *ob, const int mval[2], unsigned int *index, int size, bool use_zbuf);

@ -59,8 +59,9 @@
#include "BIF_gl.h"
#include "DNA_object_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "GPU_extensions.h"
@ -76,10 +77,12 @@
void EDBM_select_mirrored(BMEditMesh *em, bool extend,
int *r_totmirr, int *r_totfail)
{
Mesh *me = (Mesh *)em->ob->data;
BMVert *v1, *v2;
BMIter iter;
int totmirr = 0;
int totfail = 0;
bool use_topology = (me && (me->editflag & ME_EDIT_MIRROR_TOPO));
*r_totmirr = *r_totfail = 0;
@ -92,7 +95,7 @@ void EDBM_select_mirrored(BMEditMesh *em, bool extend,
}
}
EDBM_verts_mirror_cache_begin(em, 0, true, true);
EDBM_verts_mirror_cache_begin(em, 0, true, true, use_topology);
if (!extend)
EDBM_flag_disable_all(em, BM_ELEM_SELECT);

@ -1099,11 +1099,13 @@ void MESH_OT_normals_make_consistent(wmOperatorType *ot)
static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
Mesh *me = obedit->data;
BMEditMesh *em = BKE_editmesh_from_object(obedit);
ModifierData *md;
int mirrx = false, mirry = false, mirrz = false;
int i, repeat;
float clip_dist = 0.0f;
bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
const bool xaxis = RNA_boolean_get(op->ptr, "xaxis");
const bool yaxis = RNA_boolean_get(op->ptr, "yaxis");
@ -1111,7 +1113,7 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op)
/* mirror before smooth */
if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
EDBM_verts_mirror_cache_begin(em, 0, false, true);
EDBM_verts_mirror_cache_begin(em, 0, false, true, use_topology);
}
/* if there is a mirror modifier with clipping, flag the verts that
@ -1183,6 +1185,8 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
Mesh *me = obedit->data;
bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
int usex = true, usey = true, usez = true, preserve_volume = true;
int i, repeat;
float lambda_factor;
@ -1202,7 +1206,7 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op)
/* mirror before smooth */
if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
EDBM_verts_mirror_cache_begin(em, 0, false, true);
EDBM_verts_mirror_cache_begin(em, 0, false, true, use_topology);
}
repeat = RNA_int_get(op->ptr, "repeat");
@ -4257,7 +4261,7 @@ static int mesh_symmetry_snap_exec(bContext *C, wmOperator *op)
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
int *index = MEM_mallocN(bm->totvert * sizeof(*index), __func__);
const bool is_topo = false;
const bool use_topology = false;
const float thresh = RNA_float_get(op->ptr, "threshold");
const float fac = RNA_float_get(op->ptr, "factor");
@ -4276,7 +4280,7 @@ static int mesh_symmetry_snap_exec(bContext *C, wmOperator *op)
BMVert *v;
int i;
EDBM_verts_mirror_cache_begin_ex(em, axis, true, true, is_topo, thresh, index);
EDBM_verts_mirror_cache_begin_ex(em, axis, true, true, use_topology, thresh, index);
EDBM_index_arrays_ensure(em, BM_VERT);

@ -1151,13 +1151,13 @@ static BMVert *cache_mirr_intptr_as_bmvert(intptr_t *index_lookup, int index)
* \param em Editmesh.
* \param use_self Allow a vertex to point to its self (middle verts).
* \param use_select Restrict to selected verts.
* \param is_topo Use topology mirror.
* \param use_topology Use topology mirror.
* \param maxdist Distance for close point test.
* \param r_index Optional array to write into, as an alternative to a customdata layer (length of total verts).
*/
void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em, const int axis, const bool use_self, const bool use_select,
/* extra args */
const bool is_topo, float maxdist, int *r_index)
const bool use_topology, float maxdist, int *r_index)
{
Mesh *me = (Mesh *)em->ob->data;
BMesh *bm = em->bm;
@ -1188,7 +1188,7 @@ void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em, const int axis, const bool
BM_mesh_elem_index_ensure(bm, BM_VERT);
if (is_topo) {
if (use_topology) {
ED_mesh_mirrtopo_init(me, -1, &mesh_topo_store, true);
}
else {
@ -1208,7 +1208,7 @@ void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em, const int axis, const bool
BMVert *v_mirr;
int *idx = VERT_INTPTR(v, i);
if (is_topo) {
if (use_topology) {
v_mirr = cache_mirr_intptr_as_bmvert(mesh_topo_store.index_lookup, i);
}
else {
@ -1233,7 +1233,7 @@ void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em, const int axis, const bool
#undef VERT_INTPTR
if (is_topo) {
if (use_topology) {
ED_mesh_mirrtopo_free(&mesh_topo_store);
}
else {
@ -1242,17 +1242,13 @@ void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em, const int axis, const bool
}
void EDBM_verts_mirror_cache_begin(BMEditMesh *em, const int axis,
const bool use_self, const bool use_select)
const bool use_self, const bool use_select,
const bool use_topology)
{
Mesh *me = (Mesh *)em->ob->data;
bool is_topo;
is_topo = (me && (me->editflag & ME_EDIT_MIRROR_TOPO));
EDBM_verts_mirror_cache_begin_ex(em, axis,
use_self, use_select,
/* extra args */
is_topo, BM_SEARCH_MAXDIST_MIRR, NULL);
use_topology, BM_SEARCH_MAXDIST_MIRR, NULL);
}
BMVert *EDBM_verts_mirror_get(BMEditMesh *em, BMVert *v)

@ -939,9 +939,9 @@ static int mesh_get_x_mirror_vert_topo(Object *ob, int index)
return mesh_topo_store.index_lookup[index];
}
int mesh_get_x_mirror_vert(Object *ob, int index)
int mesh_get_x_mirror_vert(Object *ob, int index, const bool use_topology)
{
if (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_TOPO) {
if (use_topology) {
return mesh_get_x_mirror_vert_topo(ob, index);
}
else {
@ -1001,9 +1001,9 @@ static BMVert *editbmesh_get_x_mirror_vert_topo(Object *ob, struct BMEditMesh *e
return NULL;
}
BMVert *editbmesh_get_x_mirror_vert(Object *ob, struct BMEditMesh *em, BMVert *eve, const float co[3], int index)
BMVert *editbmesh_get_x_mirror_vert(Object *ob, struct BMEditMesh *em, BMVert *eve, const float co[3], int index, const bool use_topology)
{
if (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_TOPO) {
if (use_topology) {
return editbmesh_get_x_mirror_vert_topo(ob, em, eve, index);
}
else {
@ -1121,6 +1121,7 @@ int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em)
MVert *mv, *mvert = me->mvert;
MFace mirrormf, *mf, *hashmf, *mface = me->mface;
GHash *fhash;
const bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
int *mirrorverts, *mirrorfaces;
int a;
@ -1130,7 +1131,7 @@ int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em)
mesh_octree_table(ob, em, NULL, 's');
for (a = 0, mv = mvert; a < me->totvert; a++, mv++)
mirrorverts[a] = mesh_get_x_mirror_vert(ob, a);
mirrorverts[a] = mesh_get_x_mirror_vert(ob, a, use_topology);
mesh_octree_table(ob, em, NULL, 'e');

@ -168,7 +168,7 @@ static bool ED_object_shape_key_remove(Main *bmain, Object *ob)
}
static bool object_shape_key_mirror(bContext *C, Object *ob,
int *r_totmirr, int *r_totfail)
int *r_totmirr, int *r_totfail, bool use_topology)
{
KeyBlock *kb;
Key *key;
@ -196,7 +196,7 @@ static bool object_shape_key_mirror(bContext *C, Object *ob,
mesh_octree_table(ob, NULL, NULL, 's');
for (i1 = 0, mv = me->mvert; i1 < me->totvert; i1++, mv++) {
i2 = mesh_get_x_mirror_vert(ob, i1);
i2 = mesh_get_x_mirror_vert(ob, i1, use_topology);
if (i2 == i1) {
fp1 = ((float *)kb->data) + i1 * 3;
fp1[0] = -fp1[0];
@ -440,8 +440,9 @@ static int shape_key_mirror_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
int totmirr = 0, totfail = 0;
bool use_topology = RNA_boolean_get(op->ptr, "use_topology");
if (!object_shape_key_mirror(C, ob, &totmirr, &totfail))
if (!object_shape_key_mirror(C, ob, &totmirr, &totfail, use_topology))
return OPERATOR_CANCELLED;
ED_mesh_report_mirror(op, totmirr, totfail);
@ -462,6 +463,10 @@ void OBJECT_OT_shape_key_mirror(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
RNA_def_boolean(ot->srna, "use_topology", 0, "Topology Mirror",
"Use topology based mirroring (for when both sides of mesh have matching, unique topology)");
}

@ -438,8 +438,9 @@ static void ED_mesh_defvert_mirror_update_em(Object *ob, BMVert *eve, int def_nr
Mesh *me = ob->data;
BMEditMesh *em = me->edit_btmesh;
BMVert *eve_mirr;
bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
eve_mirr = editbmesh_get_x_mirror_vert(ob, em, eve, eve->co, vidx);
eve_mirr = editbmesh_get_x_mirror_vert(ob, em, eve, eve->co, vidx, use_topology);
if (eve_mirr && eve_mirr != eve) {
MDeformVert *dvert_src = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
@ -452,10 +453,12 @@ static void ED_mesh_defvert_mirror_update_ob(Object *ob, int def_nr, int vidx)
{
int vidx_mirr;
Mesh *me = ob->data;
bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
if (vidx == -1)
return;
vidx_mirr = mesh_get_x_mirror_vert(ob, vidx);
vidx_mirr = mesh_get_x_mirror_vert(ob, vidx, use_topology);
if ((vidx_mirr) >= 0 && (vidx_mirr != vidx)) {
MDeformVert *dvert_src = &me->dvert[vidx];
@ -2314,7 +2317,8 @@ static void dvert_mirror_op(MDeformVert *dvert, MDeformVert *dvert_mirr,
/* TODO, vgroup locking */
/* TODO, face masking */
void ED_vgroup_mirror(Object *ob,
const bool mirror_weights, const bool flip_vgroups, const bool all_vgroups,
const bool mirror_weights, const bool flip_vgroups,
const bool all_vgroups, const bool use_topology,
int *r_totmirr, int *r_totfail)
{
@ -2371,7 +2375,7 @@ void ED_vgroup_mirror(Object *ob,
goto cleanup;
}
EDBM_verts_mirror_cache_begin(em, 0, true, false);
EDBM_verts_mirror_cache_begin(em, 0, true, false, use_topology);
/* Go through the list of editverts and assign them */
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
@ -2420,7 +2424,7 @@ void ED_vgroup_mirror(Object *ob,
for (vidx = 0, mv = me->mvert; vidx < me->totvert; vidx++, mv++) {
if ((mv->flag & ME_VERT_TMP_TAG) == 0) {
if ((vidx_mirr = mesh_get_x_mirror_vert(ob, vidx)) != -1) {
if ((vidx_mirr = mesh_get_x_mirror_vert(ob, vidx, use_topology)) != -1) {
if (vidx != vidx_mirr) {
mv_mirr = &me->mvert[vidx_mirr];
if ((mv_mirr->flag & ME_VERT_TMP_TAG) == 0) {
@ -3623,6 +3627,7 @@ static int vertex_group_mirror_exec(bContext *C, wmOperator *op)
RNA_boolean_get(op->ptr, "mirror_weights"),
RNA_boolean_get(op->ptr, "flip_group_names"),
RNA_boolean_get(op->ptr, "all_groups"),
RNA_boolean_get(op->ptr, "use_topology"),
&totmirr, &totfail);
ED_mesh_report_mirror(op, totmirr, totfail);
@ -3653,7 +3658,8 @@ void OBJECT_OT_vertex_group_mirror(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "mirror_weights", true, "Mirror Weights", "Mirror weights");
RNA_def_boolean(ot->srna, "flip_group_names", true, "Flip Group Names", "Flip vertex group names");
RNA_def_boolean(ot->srna, "all_groups", false, "All Groups", "Mirror all vertex groups weights");
RNA_def_boolean(ot->srna, "use_topology", 0, "Topology Mirror",
"Use topology based mirroring (for when both sides of mesh have matching, unique topology)");
}
static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *UNUSED(op))

@ -482,6 +482,7 @@ bool ED_wpaint_fill(VPaint *wp, Object *ob, float paintweight)
MDeformWeight *dw, *dw_prev;
int vgroup_active, vgroup_mirror = -1;
unsigned int index;
const bool topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
/* mutually exclusive, could be made into a */
const short paint_selmode = ME_EDIT_PAINT_SEL_MODE(me);
@ -521,7 +522,7 @@ bool ED_wpaint_fill(VPaint *wp, Object *ob, float paintweight)
dw->weight = paintweight;
if (me->editflag & ME_EDIT_MIRROR_X) { /* x mirror painting */
int j = mesh_get_x_mirror_vert(ob, vidx);
int j = mesh_get_x_mirror_vert(ob, vidx, topology);
if (j >= 0) {
/* copy, not paint again */
if (vgroup_mirror != -1) {
@ -1790,6 +1791,7 @@ static void do_weight_paint_vertex(
{
Mesh *me = ob->data;
MDeformVert *dv = &me->dvert[index];
bool topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
MDeformWeight *dw, *dw_prev;
@ -1818,7 +1820,7 @@ static void do_weight_paint_vertex(
/* from now on we can check if mirrors enabled if this var is -1 and not bother with the flag */
if (me->editflag & ME_EDIT_MIRROR_X) {
index_mirr = mesh_get_x_mirror_vert(ob, index);
index_mirr = mesh_get_x_mirror_vert(ob, index, topology);
vgroup_mirr = (wpi->vgroup_mirror != -1) ? wpi->vgroup_mirror : wpi->vgroup_active;
/* another possible error - mirror group _and_ active group are the same (which is fine),

@ -2023,6 +2023,7 @@ static void createTransEditVerts(TransInfo *t)
TransData *tob = NULL;
TransDataExtension *tx = NULL;
BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
Mesh *me = t->obedit->data;
BMesh *bm = em->bm;
BMVert *eve;
BMIter iter;
@ -2036,9 +2037,10 @@ static void createTransEditVerts(TransInfo *t)
char *selstate = NULL;
short selectmode = ts->selectmode;
int cd_vert_bweight_offset = -1;
bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
if (t->flag & T_MIRROR) {
EDBM_verts_mirror_cache_begin(em, 0, false, (t->flag & T_PROP_EDIT) == 0);
EDBM_verts_mirror_cache_begin(em, 0, false, (t->flag & T_PROP_EDIT) == 0, use_topology);
mirror = 1;
}