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:
-rw-r--r--source/blender/editors/transform/transform_mode.c4
-rw-r--r--source/blender/editors/transform/transform_mode.h2
-rw-r--r--source/blender/editors/transform/transform_mode_mirror.c149
-rw-r--r--source/blender/editors/transform/transform_ops.c3
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)