Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2013-09-17 11:03:13 +0400
committerCampbell Barton <ideasman42@gmail.com>2013-09-17 11:03:13 +0400
commit0b22cfb1d14f49393042160e4beadf351f171ddc (patch)
tree16bad1ddd6be12fdd9f4b82de7990760fbbb0c5b /source/blender/editors
parent0002d3d85f4c4e6d3084e468fa844e717719ab4d (diff)
fix [#36246] Weight tools do not mirror properly in vertex selection mask mode.
Weight mirror is now supported by invert/clean/levels/blend.
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/include/ED_mesh.h10
-rw-r--r--source/blender/editors/mesh/meshtools.c25
-rw-r--r--source/blender/editors/object/object_vgroup.c189
3 files changed, 192 insertions, 32 deletions
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 51f888be37e..b7fd181883b 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -246,6 +246,14 @@ bool ED_vgroup_array_get(struct ID *id, struct MDeformVert **dve
bool ED_vgroup_array_copy(struct Object *ob, struct Object *ob_from);
bool ED_vgroup_parray_alloc(struct ID *id, struct MDeformVert ***dvert_arr, int *dvert_tot,
const bool use_vert_sel);
+void ED_vgroup_parray_mirror_sync(struct Object *ob,
+ struct MDeformVert **dvert_array, const int dvert_tot,
+ const bool *vgroup_validmap, const int vgroup_tot);
+void ED_vgroup_parray_mirror_assign(struct Object *ob,
+ struct MDeformVert **dvert_array, const int dvert_tot);
+void ED_vgroup_parray_remove_zero(struct MDeformVert **dvert_array, const int dvert_tot,
+ const bool *vgroup_validmap, const int vgroup_tot,
+ const float epsilon, const bool keep_single);
void ED_vgroup_mirror(struct Object *ob,
const bool mirror_weights, const bool flip_vgroups,
const bool all_vgroups, const bool use_topology,
@@ -319,6 +327,8 @@ struct BMVert *editbmesh_get_x_mirror_vert(struct Object *ob, struct BMEditMesh
int index, const bool use_topology);
int *mesh_get_x_mirror_faces(struct Object *ob, struct BMEditMesh *em);
+int ED_mesh_mirror_get_vert(struct Object *ob, int index);
+
bool ED_mesh_pick_vert(struct bContext *C, struct Object *ob, const int mval[2], unsigned int *index, int size, bool use_zbuf);
bool ED_mesh_pick_face(struct bContext *C, struct Object *ob, const int mval[2], unsigned int *index, int size);
bool ED_mesh_pick_face_vert(struct bContext *C, struct Object *ob, const int mval[2], unsigned int *index, int size);
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index ce1cacdfb3a..efa619bd10c 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -1011,6 +1011,31 @@ BMVert *editbmesh_get_x_mirror_vert(Object *ob, struct BMEditMesh *em, BMVert *e
}
}
+/**
+ * Wrapper for objectmode/editmode.
+ *
+ * call #EDBM_index_arrays_ensure first for editmesh.
+ */
+int ED_mesh_mirror_get_vert(Object *ob, int index)
+{
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_btmesh;
+ bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
+ int index_mirr;
+
+ if (em) {
+ BMVert *eve, *eve_mirr;
+ eve = EDBM_vert_at_index(em, index);
+ eve_mirr = editbmesh_get_x_mirror_vert(ob, em, eve, eve->co, index, use_topology);
+ index_mirr = eve_mirr ? BM_elem_index_get(eve_mirr) : -1;
+ }
+ else {
+ index_mirr = mesh_get_x_mirror_vert(ob, index, use_topology);
+ }
+
+ return index_mirr;
+}
+
#if 0
static float *editmesh_get_mirror_uv(BMEditMesh *em, int axis, float *uv, float *mirrCent, float *face_cent)
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index 14692a3051c..917f816d6b1 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -326,6 +326,119 @@ bool ED_vgroup_parray_alloc(ID *id, MDeformVert ***dvert_arr, int *dvert_tot, co
return false;
}
+/**
+ * For use with tools that use ED_vgroup_parray_alloc with \a use_vert_sel == true.
+ * This finds the unselected mirror deform verts and copys the weights to them from the selected.
+ *
+ * \note \a dvert_array has mirrored weights filled in, incase cleanup operations are needed on both.
+ */
+void ED_vgroup_parray_mirror_sync(Object *ob,
+ MDeformVert **dvert_array, const int dvert_tot,
+ const bool *vgroup_validmap, const int vgroup_tot)
+{
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ MDeformVert **dvert_array_all = NULL;
+ int dvert_tot_all;
+ int i;
+
+ /* get an array of all verts, not only selected */
+ if (ED_vgroup_parray_alloc(ob->data, &dvert_array_all, &dvert_tot_all, false) == false) {
+ BLI_assert(0);
+ return;
+ }
+ if (em) {
+ EDBM_index_arrays_ensure(em, BM_VERT);
+ }
+
+ for (i = 0; i < dvert_tot; i++) {
+ if (dvert_array[i] == NULL) {
+ /* its unselected, check if its mirror is */
+ int i_sel = ED_mesh_mirror_get_vert(ob, i);
+ if ((i_sel != -1) && (i_sel != i) && (dvert_array[i_sel])) {
+ /* we found a match! */
+ MDeformVert *dv_src = dvert_array[i_sel];
+ MDeformVert *dv_dst = dvert_array_all[i];
+
+ defvert_copy_subset(dv_dst, dv_src, vgroup_validmap, vgroup_tot);
+
+ dvert_array[i] = dvert_array_all[i];
+ }
+ }
+ }
+
+ MEM_freeN(dvert_array_all);
+}
+
+/**
+ * Fill in the pointers for mirror verts (as if all mirror verts were selected too).
+ *
+ * similar to #ED_vgroup_parray_mirror_sync but only fill in mirror points.
+ */
+void ED_vgroup_parray_mirror_assign(Object *ob,
+ MDeformVert **dvert_array, const int dvert_tot)
+{
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ MDeformVert **dvert_array_all = NULL;
+ int dvert_tot_all;
+ int i;
+
+ /* get an array of all verts, not only selected */
+ if (ED_vgroup_parray_alloc(ob->data, &dvert_array_all, &dvert_tot_all, false) == false) {
+ BLI_assert(0);
+ return;
+ }
+ BLI_assert(dvert_tot == dvert_tot_all);
+ if (em) {
+ EDBM_index_arrays_ensure(em, BM_VERT);
+ }
+
+ for (i = 0; i < dvert_tot; i++) {
+ if (dvert_array[i] == NULL) {
+ /* its unselected, check if its mirror is */
+ int i_sel = ED_mesh_mirror_get_vert(ob, i);
+ if ((i_sel != -1) && (i_sel != i) && (dvert_array[i_sel])) {
+ /* we found a match! */
+ dvert_array[i] = dvert_array_all[i];
+ }
+ }
+ }
+
+ MEM_freeN(dvert_array_all);
+}
+
+void ED_vgroup_parray_remove_zero(MDeformVert **dvert_array, const int dvert_tot,
+ const bool *vgroup_validmap, const int vgroup_tot,
+ const float epsilon, const bool keep_single)
+{
+ MDeformVert *dv;
+ int i;
+
+ for (i = 0; i < dvert_tot; i++) {
+ int j;
+
+ /* in case its not selected */
+ if (!(dv = dvert_array[i])) {
+ continue;
+ }
+
+ j = dv->totweight;
+
+ while (j--) {
+ MDeformWeight *dw;
+
+ if (keep_single && dv->totweight == 1)
+ break;
+
+ dw = dv->dw + j;
+ if ((dw->def_nr < vgroup_tot) && vgroup_validmap[dw->def_nr]) {
+ if (dw->weight <= epsilon) {
+ defvert_remove_group(dv, dw);
+ }
+ }
+ }
+ }
+}
+
/* returns true if the id type supports weights */
bool ED_vgroup_array_get(ID *id, MDeformVert **dvert_arr, int *dvert_tot)
{
@@ -1850,7 +1963,8 @@ static void vgroup_levels_subset(Object *ob, const bool *vgroup_validmap, const
MDeformVert *dv, **dvert_array = NULL;
int i, dvert_tot = 0;
- const int use_vert_sel = vertex_group_use_vert_sel(ob);
+ const bool use_vert_sel = vertex_group_use_vert_sel(ob);
+ const bool use_mirror = (ob->type == OB_MESH) ? (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 : false;
ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
@@ -1877,6 +1991,11 @@ static void vgroup_levels_subset(Object *ob, const bool *vgroup_validmap, const
}
}
+ if (use_mirror && use_vert_sel) {
+ ED_vgroup_parray_mirror_sync(ob, dvert_array, dvert_tot,
+ vgroup_validmap, vgroup_tot);
+ }
+
MEM_freeN(dvert_array);
}
}
@@ -1980,7 +2099,8 @@ static void vgroup_invert_subset(Object *ob,
MDeformWeight *dw;
MDeformVert *dv, **dvert_array = NULL;
int i, dvert_tot = 0;
- const int use_vert_sel = vertex_group_use_vert_sel(ob);
+ const bool use_vert_sel = vertex_group_use_vert_sel(ob);
+ const bool use_mirror = (ob->type == OB_MESH) ? (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 : false;
ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
@@ -2006,14 +2126,23 @@ static void vgroup_invert_subset(Object *ob,
if (dw) {
dw->weight = 1.0f - dw->weight;
- if (auto_remove && dw->weight <= 0.0f) {
- defvert_remove_group(dv, dw);
- }
+ CLAMP(dw->weight, 0.0f, 1.0f);
}
}
}
}
+ if (use_mirror && use_vert_sel) {
+ ED_vgroup_parray_mirror_sync(ob, dvert_array, dvert_tot,
+ vgroup_validmap, vgroup_tot);
+
+ if (auto_remove) {
+ ED_vgroup_parray_remove_zero(dvert_array, dvert_tot,
+ vgroup_validmap, vgroup_tot,
+ 0.0f, false);
+ }
+ }
+
MEM_freeN(dvert_array);
}
}
@@ -2027,6 +2156,7 @@ static void vgroup_blend_subset(Object *ob, const bool *vgroup_validmap, const i
int i, dvert_tot = 0;
int *vgroup_subset_map = BLI_array_alloca(vgroup_subset_map, subset_count);
float *vgroup_subset_weights = BLI_array_alloca(vgroup_subset_weights, subset_count);
+ const bool use_mirror = (ob->type == OB_MESH) ? (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 : false;
BMEditMesh *em = BKE_editmesh_from_object(ob);
BMesh *bm = em ? em->bm : NULL;
@@ -2042,6 +2172,8 @@ static void vgroup_blend_subset(Object *ob, const bool *vgroup_validmap, const i
memset(vgroup_subset_weights, 0, sizeof(*vgroup_subset_weights) * subset_count);
if (bm) {
+ EDBM_index_arrays_ensure(em, BM_VERT);
+
emap = NULL;
emap_mem = NULL;
}
@@ -2132,6 +2264,14 @@ static void vgroup_blend_subset(Object *ob, const bool *vgroup_validmap, const i
MEM_freeN(dvert_array);
BLI_SMALLSTACK_FREE(dv_stack);
+
+ /* not so efficient to get 'dvert_array' again just so unselected verts are NULL'd */
+ if (use_mirror) {
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, true);
+ ED_vgroup_parray_mirror_sync(ob, dvert_array, dvert_tot,
+ vgroup_validmap, vgroup_tot);
+ MEM_freeN(dvert_array);
+ }
}
static int inv_cmp_mdef_vert_weights(const void *a1, const void *a2)
@@ -2227,39 +2367,24 @@ static void vgroup_clean_subset(Object *ob, const bool *vgroup_validmap, const i
const float epsilon, const bool keep_single)
{
MDeformVert **dvert_array = NULL;
- int i, dvert_tot = 0;
- const int use_vert_sel = vertex_group_use_vert_sel(ob);
+ int dvert_tot = 0;
+ const bool use_vert_sel = vertex_group_use_vert_sel(ob);
+ const bool use_mirror = (ob->type == OB_MESH) ? (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 : false;
ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
if (dvert_array) {
- MDeformVert *dv;
- MDeformWeight *dw;
-
- for (i = 0; i < dvert_tot; i++) {
- int j;
-
- /* in case its not selected */
- if (!(dv = dvert_array[i])) {
- continue;
- }
-
- j = dv->totweight;
-
- while (j--) {
-
- if (keep_single && dv->totweight == 1)
- break;
-
- dw = dv->dw + j;
- if ((dw->def_nr < vgroup_tot) && vgroup_validmap[dw->def_nr]) {
- if (dw->weight <= epsilon) {
- defvert_remove_group(dv, dw);
- }
- }
- }
+ if (use_mirror && use_vert_sel) {
+ /* correct behavior in this case isn't well defined
+ * for now assume both sides are mirrored correctly,
+ * so cleaning one side also cleans the other */
+ ED_vgroup_parray_mirror_assign(ob, dvert_array, dvert_tot);
}
+ ED_vgroup_parray_remove_zero(dvert_array, dvert_tot,
+ vgroup_validmap, vgroup_tot,
+ epsilon, keep_single);
+
MEM_freeN(dvert_array);
}
}