diff options
Diffstat (limited to 'source/blender/editors/transform')
4 files changed, 141 insertions, 17 deletions
diff --git a/source/blender/editors/transform/transform_mode.c b/source/blender/editors/transform/transform_mode.c index af0a8e5e505..a4d999b868d 100644 --- a/source/blender/editors/transform/transform_mode.c +++ b/source/blender/editors/transform/transform_mode.c @@ -228,7 +228,7 @@ static void protectedAxisAngleBits( } } -static void protectedSizeBits(short protectflag, float size[3]) +void protectedSizeBits(short protectflag, float size[3]) { if (protectflag & OB_LOCK_SCALEX) { size[0] = 1.0f; @@ -431,7 +431,7 @@ static void constraintRotLim(TransInfo *UNUSED(t), TransData *td) } } -static void constraintSizeLim(TransInfo *t, TransData *td) +void constraintSizeLim(TransInfo *t, TransData *td) { if (td->con && td->ext) { const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_SIZELIMIT); diff --git a/source/blender/editors/transform/transform_mode.h b/source/blender/editors/transform/transform_mode.h index df7d10d1028..7a05506e12c 100644 --- a/source/blender/editors/transform/transform_mode.h +++ b/source/blender/editors/transform/transform_mode.h @@ -44,7 +44,9 @@ int transform_mode_really_used(struct bContext *C, int mode); bool transdata_check_local_center(TransInfo *t, short around); bool transform_mode_is_changeable(const int mode); void protectedTransBits(short protectflag, float vec[3]); +void protectedSizeBits(short protectflag, float size[3]); void constraintTransLim(TransInfo *t, TransData *td); +void constraintSizeLim(TransInfo *t, TransData *td); void postInputRotation(TransInfo *t, float values[3]); void headerRotation(TransInfo *t, char *str, float final); void ElementRotation_ex(TransInfo *t, diff --git a/source/blender/editors/transform/transform_mode_mirror.c b/source/blender/editors/transform/transform_mode_mirror.c index 1440553de51..3aa99975fda 100644 --- a/source/blender/editors/transform/transform_mode_mirror.c +++ b/source/blender/editors/transform/transform_mode_mirror.c @@ -24,8 +24,10 @@ #include <stdlib.h> #include "BLI_math.h" +#include "BLI_math_bits.h" #include "BLI_string.h" +#include "BKE_armature.h" #include "BKE_context.h" #include "ED_screen.h" @@ -41,9 +43,130 @@ /** \name Transform (Mirror) * \{ */ +/** + * Mirrors an object by negating the scale of the object on the mirror axis, reflecting the + * location and adjusting the rotation. + * + * \param axis: Either the axis to mirror on (0 = x, 1 = y, 2 = z) in transform space or -1 for no + * axis mirror. + * \param flip: If true, a mirror on all axis will be performed additionally (point + * reflection). + */ +static void ElementMirror(TransInfo *t, TransDataContainer *tc, TransData *td, int axis, bool flip) +{ + if ((t->flag & T_V3D_ALIGN) == 0 && td->ext) { + /* Size checked needed since the 3D cursor only uses rotation fields. */ + if (td->ext->size) { + float fsize[] = {1.0, 1.0, 1.0}; + + if (axis >= 0) { + fsize[axis] = -fsize[axis]; + } + if (flip) { + negate_v3(fsize); + } + + protectedSizeBits(td->protectflag, fsize); + + mul_v3_v3v3(td->ext->size, td->ext->isize, fsize); + + constraintSizeLim(t, td); + } + + float rmat[3][3]; + if (axis >= 0) { + float imat[3][3]; + mul_m3_m3m3(rmat, t->spacemtx_inv, td->axismtx); + rmat[axis][0] = -rmat[axis][0]; + rmat[axis][1] = -rmat[axis][1]; + rmat[axis][2] = -rmat[axis][2]; + rmat[0][axis] = -rmat[0][axis]; + rmat[1][axis] = -rmat[1][axis]; + rmat[2][axis] = -rmat[2][axis]; + invert_m3_m3(imat, td->axismtx); + mul_m3_m3m3(rmat, rmat, imat); + mul_m3_m3m3(rmat, t->spacemtx, rmat); + + ElementRotation_ex(t, tc, td, rmat, td->center); + + if (td->ext->rotAngle) { + *td->ext->rotAngle = -td->ext->irotAngle; + } + } + else { + unit_m3(rmat); + ElementRotation_ex(t, tc, td, rmat, td->center); + + if (td->ext->rotAngle) { + *td->ext->rotAngle = td->ext->irotAngle; + } + } + } + + if ((td->flag & TD_NO_LOC) == 0) { + float center[3], vec[3]; + + /* Local constraint shouldn't alter center. */ + if (transdata_check_local_center(t, t->around)) { + copy_v3_v3(center, td->center); + } + else if (t->options & CTX_MOVIECLIP) { + if (td->flag & TD_INDIVIDUAL_SCALE) { + copy_v3_v3(center, td->center); + } + else { + copy_v3_v3(center, tc->center_local); + } + } + else { + copy_v3_v3(center, tc->center_local); + } + + /* For individual element center, Editmode need to use iloc. */ + if (t->flag & T_POINTS) { + sub_v3_v3v3(vec, td->iloc, center); + } + else { + sub_v3_v3v3(vec, td->center, center); + } + + if (axis >= 0) { + /* Always do the mirror in global space. */ + if (t->flag & T_EDIT) { + mul_m3_v3(td->mtx, vec); + } + reflect_v3_v3v3(vec, vec, t->spacemtx[axis]); + if (t->flag & T_EDIT) { + mul_m3_v3(td->smtx, vec); + } + } + if (flip) { + negate_v3(vec); + } + + add_v3_v3(vec, center); + if (t->flag & T_POINTS) { + sub_v3_v3(vec, td->iloc); + } + else { + sub_v3_v3(vec, td->center); + } + + if (t->flag & (T_OBJECT | T_POSE)) { + mul_m3_v3(td->smtx, vec); + } + + protectedTransBits(td->protectflag, vec); + if (td->loc) { + add_v3_v3v3(td->loc, td->iloc, vec); + } + + constraintTransLim(t, td); + } +} + static void applyMirror(TransInfo *t, const int UNUSED(mval[2])) { - float size[3], mat[3][3]; int i; char str[UI_MAX_DRAW_STR]; copy_v3_v3(t->values_final, t->values); @@ -54,12 +177,16 @@ static void applyMirror(TransInfo *t, const int UNUSED(mval[2])) /* if an axis has been selected */ if (t->con.mode & CON_APPLY) { - size[0] = size[1] = size[2] = -1; - - size_to_mat3(mat, size); - - if (t->con.applySize) { - t->con.applySize(t, NULL, NULL, mat); + /* #special_axis is either the constraint plane normal or the constraint axis. + * Assuming that CON_AXIS0 < CON_AXIS1 < CON_AXIS2 and CON_AXIS2 is CON_AXIS0 << 2 */ + BLI_assert(CON_AXIS2 == CON_AXIS0 << 2); + int axis_bitmap = (t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2)) / CON_AXIS0; + int special_axis_bitmap = 0; + int special_axis = -1; + int bitmap_len = count_bits_i(axis_bitmap); + if (LIKELY(!ELEM(bitmap_len, 0, 3))) { + special_axis_bitmap = (bitmap_len == 2) ? ~axis_bitmap : axis_bitmap; + special_axis = bitscan_forward_i(special_axis_bitmap); } BLI_snprintf(str, sizeof(str), TIP_("Mirror%s"), t->con.text); @@ -71,7 +198,7 @@ static void applyMirror(TransInfo *t, const int UNUSED(mval[2])) continue; } - ElementResize(t, tc, td, mat); + ElementMirror(t, tc, td, special_axis, bitmap_len >= 2); } } @@ -80,10 +207,6 @@ static void applyMirror(TransInfo *t, const int UNUSED(mval[2])) ED_area_status_text(t->area, str); } else { - size[0] = size[1] = size[2] = 1; - - size_to_mat3(mat, size); - FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { @@ -91,7 +214,7 @@ static void applyMirror(TransInfo *t, const int UNUSED(mval[2])) continue; } - ElementResize(t, tc, td, mat); + ElementMirror(t, tc, td, -1, false); } } diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index aeb34e34d97..7282c35ea0f 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -1040,8 +1040,7 @@ static void TRANSFORM_OT_mirror(struct wmOperatorType *ot) ot->poll = ED_operator_screenactive; ot->poll_property = transform_poll_property; - Transform_Properties( - ot, P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_GPENCIL_EDIT | P_CENTER); + Transform_Properties(ot, P_ORIENT_MATRIX | P_CONSTRAINT | P_GPENCIL_EDIT | P_CENTER); } static void TRANSFORM_OT_bbone_resize(struct wmOperatorType *ot) |