Fix T57852: Mesh X Mirror option not working

D3869 by @lichtwerk w/ own edits
This commit is contained in:
Campbell Barton 2019-01-14 14:59:18 +11:00
parent 9c7adcfd8b
commit 65b82e09d9
Notes: blender-bot 2023-02-14 08:38:11 +01:00
Referenced by issue #57852, Edit Mesh: X-Mirror/Topology Mirror not working
4 changed files with 63 additions and 48 deletions

View File

@ -2171,7 +2171,7 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
}
if ((prop = RNA_struct_find_property(op->ptr, "mirror"))) {
RNA_property_boolean_set(op->ptr, prop, (t->flag & T_MIRROR) != 0);
RNA_property_boolean_set(op->ptr, prop, (t->flag & T_NO_MIRROR) == 0);
}
if ((prop = RNA_struct_find_property(op->ptr, "constraint_axis"))) {
@ -5980,7 +5980,7 @@ static void slide_origdata_create_data_vert(
}
static void slide_origdata_create_data(
TransInfo *t, TransDataContainer *tc, SlideOrigData *sod,
TransDataContainer *tc, SlideOrigData *sod,
TransDataGenericSlideVert *sv_array, unsigned int v_stride, unsigned int v_num)
{
if (sod->use_origfaces) {
@ -6015,7 +6015,7 @@ static void slide_origdata_create_data(
slide_origdata_create_data_vert(bm, sod, sv);
}
if (t->flag & T_MIRROR) {
if (tc->mirror.axis_flag) {
TransData *td = tc->data;
TransDataGenericSlideVert *sv_mirror;
@ -6995,7 +6995,7 @@ static bool createEdgeSlideVerts_double_side(TransInfo *t, TransDataContainer *t
/* create copies of faces for customdata projection */
bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
slide_origdata_init_data(tc, &sld->orig_data);
slide_origdata_create_data(t, tc, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv);
slide_origdata_create_data(tc, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv);
if (rv3d) {
calcEdgeSlide_even(t, tc, sld, mval);
@ -7190,7 +7190,7 @@ static bool createEdgeSlideVerts_single_side(TransInfo *t, TransDataContainer *t
/* create copies of faces for customdata projection */
bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
slide_origdata_init_data(tc, &sld->orig_data);
slide_origdata_create_data(t, tc, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv);
slide_origdata_create_data(tc, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv);
if (rv3d) {
calcEdgeSlide_even(t, tc, sld, mval);
@ -7806,7 +7806,7 @@ static bool createVertSlideVerts(TransInfo *t, TransDataContainer *tc)
bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
slide_origdata_init_data(tc, &sld->orig_data);
slide_origdata_create_data(t, tc, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv);
slide_origdata_create_data(tc, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv);
sld->em = em;

View File

@ -514,6 +514,16 @@ typedef struct TransDataContainer {
/** Center of transformation (in local-space), Calculated from #TransInfo.center_global. */
float center_local[3];
/**
* Mirror option
*/
struct {
/* Currently for mesh X mirror only. */
int axis_flag;
/** Set to -1.0f or 1.0 when use_mirror is set. */
float sign;
} mirror;
TransCustomDataContainer custom;
} TransDataContainer;
@ -618,8 +628,6 @@ typedef struct TransInfo {
short prop_mode;
short mirror;
float values[4];
/** Offset applied ontop of modal input. */
float values_modal_offset[4];
@ -710,7 +718,8 @@ enum {
/** Auto-ik is on. */
T_AUTOIK = 1 << 18,
T_MIRROR = 1 << 19,
/** Don't use mirror even if the data-block option is set. */
T_NO_MIRROR = 1 << 19,
T_AUTOVALUES = 1 << 20,

View File

@ -2676,12 +2676,9 @@ static void createTransEditVerts(TransInfo *t)
* Optional, allocate if needed. */
int *dists_index = NULL;
if (t->flag & T_MIRROR) {
/* TODO(campbell): xform: We need support for many mirror objects at once! */
if (tc->is_active) {
EDBM_verts_mirror_cache_begin(em, 0, false, (t->flag & T_PROP_EDIT) == 0, use_topology);
mirror = 1;
}
if (tc->mirror.axis_flag) {
EDBM_verts_mirror_cache_begin(em, 0, false, (t->flag & T_PROP_EDIT) == 0, use_topology);
mirror = 1;
}
/**
@ -2791,7 +2788,7 @@ static void createTransEditVerts(TransInfo *t)
BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(eve, BM_ELEM_SELECT) && eve->co[0] != 0.0f) {
if (eve->co[0] < 0.0f) {
t->mirror = -1;
tc->mirror.sign = -1.0f;
mirror = -1;
}
break;
@ -2895,7 +2892,7 @@ cleanup:
if (dists_index)
MEM_freeN(dists_index);
if (t->flag & T_MIRROR) {
if (tc->mirror.axis_flag) {
EDBM_verts_mirror_cache_end(em);
}
}
@ -6381,7 +6378,7 @@ static void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t)
char hflag;
bool has_face_sel = (bm->totfacesel != 0);
if (t->flag & T_MIRROR) {
if (tc->mirror.axis_flag) {
TransData *td;
int i;

View File

@ -237,27 +237,29 @@ static void clipMirrorModifier(TransInfo *t)
static void editbmesh_apply_to_mirror(TransInfo *t)
{
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
BMVert *eve;
int i;
if (tc->mirror.axis_flag) {
TransData *td = tc->data;
BMVert *eve;
int i;
for (i = 0; i < tc->data_len; i++, td++) {
if (td->flag & TD_NOACTION)
break;
if (td->loc == NULL)
break;
if (td->flag & TD_SKIP)
continue;
for (i = 0; i < tc->data_len; i++, td++) {
if (td->flag & TD_NOACTION)
break;
if (td->loc == NULL)
break;
if (td->flag & TD_SKIP)
continue;
eve = td->extra;
if (eve) {
eve->co[0] = -td->loc[0];
eve->co[1] = td->loc[1];
eve->co[2] = td->loc[2];
}
eve = td->extra;
if (eve) {
eve->co[0] = -td->loc[0];
eve->co[1] = td->loc[1];
eve->co[2] = td->loc[2];
}
if (td->flag & TD_MIRROR_EDGE) {
td->loc[0] = 0;
if (td->flag & TD_MIRROR_EDGE) {
td->loc[0] = 0;
}
}
}
}
@ -812,8 +814,11 @@ static void recalcData_objects(TransInfo *t)
applyProject(t);
clipMirrorModifier(t);
}
if ((t->options & CTX_NO_MIRROR) == 0 && (t->flag & T_MIRROR))
if ((t->flag & T_NO_MIRROR) == 0 &&
(t->options & CTX_NO_MIRROR) == 0)
{
editbmesh_apply_to_mirror(t);
}
if (t->mode == TFM_EDGE_SLIDE) {
projectEdgeSlideData(t, false);
@ -1227,6 +1232,12 @@ void initTransDataContainers_FromObjectData(TransInfo *t, Object *obact, Object
for (int i = 0; i < objects_len; i++) {
TransDataContainer *tc = &t->data_container[i];
/* TODO, multiple axes. */
tc->mirror.axis_flag = (
((t->flag & T_NO_MIRROR) == 0) &&
((t->options & CTX_NO_MIRROR) == 0) &&
(((Mesh *)objects[i]->data)->editflag & ME_EDIT_MIRROR_X) != 0);
if (object_mode & OB_MODE_EDIT) {
tc->obedit = objects[i];
/* Check needed for UV's */
@ -1548,18 +1559,16 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
if (op && ((prop = RNA_struct_find_property(op->ptr, "mirror")) &&
RNA_property_is_set(op->ptr, prop)))
{
if (RNA_property_boolean_get(op->ptr, prop)) {
t->flag |= T_MIRROR;
t->mirror = 1;
if (!RNA_property_boolean_get(op->ptr, prop)) {
t->flag |= T_NO_MIRROR;
}
}
// Need stuff to take it from edit mesh or whatnot here
else if (t->spacetype == SPACE_VIEW3D) {
/* TODO(campbell): xform, get mirror from each object. */
if (t->obedit_type == OB_MESH && (((Mesh *)OBACT(t->view_layer)->data)->editflag & ME_EDIT_MIRROR_X)) {
t->flag |= T_MIRROR;
t->mirror = 1;
}
else if ((t->spacetype == SPACE_VIEW3D) && (t->obedit_type == OB_MESH)) {
/* pass */
}
else {
/* Avoid mirroring for unsupported contexts. */
t->options |= CTX_NO_MIRROR;
}
/* setting PET flag only if property exist in operator. Otherwise, assume it's not supported */
@ -2168,7 +2177,7 @@ void calculatePropRatio(TransInfo *t)
if (td->flag & TD_SELECTED) {
td->factor = 1.0f;
}
else if (t->flag & T_MIRROR && td->loc[0] * t->mirror < -0.00001f) {
else if (tc->mirror.axis_flag && (td->loc[0] * tc->mirror.sign) < -0.00001f) {
td->flag |= TD_SKIP;
td->factor = 0.0f;
restoreElement(td);