Blender V4.3
transform_mode_mirror.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <cstdlib>
10
11#include "BLI_math_bits.h"
12#include "BLI_math_matrix.h"
13#include "BLI_math_vector.h"
14#include "BLI_string.h"
15
16#include "ED_screen.hh"
17
18#include "UI_interface.hh"
19
20#include "BLT_translation.hh"
21
22#include "transform.hh"
23#include "transform_convert.hh"
24
25#include "transform_mode.hh"
26
27/* -------------------------------------------------------------------- */
40static void ElementMirror(TransInfo *t, TransDataContainer *tc, TransData *td, int axis, bool flip)
41{
42 if ((t->flag & T_V3D_ALIGN) == 0 && td->ext) {
43 /* Size checked needed since the 3D cursor only uses rotation fields. */
44 if (td->ext->size) {
45 float fsize[] = {1.0, 1.0, 1.0};
46
47 if (axis >= 0) {
48 fsize[axis] = -fsize[axis];
49 }
50 if (flip) {
51 negate_v3(fsize);
52 }
53
55
56 mul_v3_v3v3(td->ext->size, td->ext->isize, fsize);
57
58 constraintSizeLim(t, tc, td);
59 }
60
61 float rmat[3][3];
62 if (axis >= 0) {
63 float imat[3][3];
64 mul_m3_m3m3(rmat, t->spacemtx_inv, td->axismtx);
65 rmat[axis][0] = -rmat[axis][0];
66 rmat[axis][1] = -rmat[axis][1];
67 rmat[axis][2] = -rmat[axis][2];
68 rmat[0][axis] = -rmat[0][axis];
69 rmat[1][axis] = -rmat[1][axis];
70 rmat[2][axis] = -rmat[2][axis];
71 invert_m3_m3(imat, td->axismtx);
72 mul_m3_m3m3(rmat, rmat, imat);
73 mul_m3_m3m3(rmat, t->spacemtx, rmat);
74
75 ElementRotation_ex(t, tc, td, rmat, td->center);
76
77 if (td->ext->rotAngle) {
78 *td->ext->rotAngle = -td->ext->irotAngle;
79 }
80 }
81 else {
82 unit_m3(rmat);
83 ElementRotation_ex(t, tc, td, rmat, td->center);
84
85 if (td->ext->rotAngle) {
86 *td->ext->rotAngle = td->ext->irotAngle;
87 }
88 }
89 }
90
91 if ((td->flag & TD_NO_LOC) == 0) {
92 float center[3], vec[3];
93
94 /* Local constraint shouldn't alter center. */
96 copy_v3_v3(center, td->center);
97 }
98 else if (t->options & CTX_MOVIECLIP) {
99 if (td->flag & TD_INDIVIDUAL_SCALE) {
100 copy_v3_v3(center, td->center);
101 }
102 else {
103 copy_v3_v3(center, tc->center_local);
104 }
105 }
106 else {
107 copy_v3_v3(center, tc->center_local);
108 }
109
110 /* For individual element center, Editmode need to use iloc. */
111 if (t->flag & T_POINTS) {
112 sub_v3_v3v3(vec, td->iloc, center);
113 }
114 else {
115 sub_v3_v3v3(vec, td->center, center);
116 }
117
118 if (axis >= 0) {
119 /* Always do the mirror in global space. */
120 if (t->flag & T_EDIT) {
121 mul_m3_v3(td->mtx, vec);
122 }
123 reflect_v3_v3v3(vec, vec, t->spacemtx[axis]);
124 if (t->flag & T_EDIT) {
125 mul_m3_v3(td->smtx, vec);
126 }
127 }
128 if (flip) {
129 negate_v3(vec);
130 }
131
132 add_v3_v3(vec, center);
133 if (t->flag & T_POINTS) {
134 sub_v3_v3(vec, td->iloc);
135 }
136 else {
137 sub_v3_v3(vec, td->center);
138 }
139
140 if (t->options & (CTX_OBJECT | CTX_POSE_BONE)) {
141 mul_m3_v3(td->smtx, vec);
142 }
143
145 if (td->loc) {
146 add_v3_v3v3(td->loc, td->iloc, vec);
147 }
148
149 constraintTransLim(t, tc, td);
150 }
151}
152
153static void applyMirror(TransInfo *t)
154{
155 int i;
156 char str[UI_MAX_DRAW_STR];
158
159 /* OPTIMIZATION:
160 * This still recalculates transformation on mouse move
161 * while it should only recalculate on constraint change. */
162
163 /* If an axis has been selected. */
164 if (t->con.mode & CON_APPLY) {
165 /* #special_axis is either the constraint plane normal or the constraint axis.
166 * Assuming that CON_AXIS0 < CON_AXIS1 < CON_AXIS2 and CON_AXIS2 is CON_AXIS0 << 2 */
168 int axis_bitmap = (t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2)) / CON_AXIS0;
169 int special_axis_bitmap = 0;
170 int special_axis = -1;
171 int bitmap_len = count_bits_i(axis_bitmap);
172 if (LIKELY(!ELEM(bitmap_len, 0, 3))) {
173 special_axis_bitmap = (bitmap_len == 2) ? ~axis_bitmap : axis_bitmap;
174 special_axis = bitscan_forward_i(special_axis_bitmap);
175 }
176
177 SNPRINTF(str, IFACE_("Mirror%s"), t->con.text);
178
180 TransData *td = tc->data;
181 for (i = 0; i < tc->data_len; i++, td++) {
182 if (td->flag & TD_SKIP) {
183 continue;
184 }
185
186 ElementMirror(t, tc, td, special_axis, bitmap_len >= 2);
187 }
188 }
189
190 recalc_data(t);
191
193 }
194 else {
196 TransData *td = tc->data;
197 for (i = 0; i < tc->data_len; i++, td++) {
198 if (td->flag & TD_SKIP) {
199 continue;
200 }
201
202 ElementMirror(t, tc, td, -1, false);
203 }
204 }
205
206 recalc_data(t);
207
208 if (t->flag & T_2D_EDIT) {
209 ED_area_status_text(t->area, IFACE_("Select a mirror axis (X, Y)"));
210 }
211 else {
212 ED_area_status_text(t->area, IFACE_("Select a mirror axis (X, Y, Z)"));
213 }
214 }
215}
216
217static void initMirror(TransInfo *t, wmOperator * /*op*/)
218{
220}
221
225 /*flags*/ T_NULL_ONE,
226 /*init_fn*/ initMirror,
227 /*transform_fn*/ applyMirror,
228 /*transform_matrix_fn*/ nullptr,
229 /*handle_event_fn*/ nullptr,
230 /*snap_distance_fn*/ nullptr,
231 /*snap_apply_fn*/ nullptr,
232 /*draw_fn*/ nullptr,
233};
#define BLI_assert(a)
Definition BLI_assert.h:50
MINLINE int bitscan_forward_i(int a)
MINLINE int count_bits_i(unsigned int n)
void mul_m3_v3(const float M[3][3], float r[3])
void unit_m3(float m[3][3])
bool invert_m3_m3(float inverse[3][3], const float mat[3][3])
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
MINLINE void sub_v3_v3(float r[3], const float a[3])
void reflect_v3_v3v3(float out[3], const float v[3], const float normal[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void negate_v3(float r[3])
MINLINE void mul_v3_v3v3(float r[3], const float v1[3], const float v2[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:597
#define ELEM(...)
#define LIKELY(x)
#define IFACE_(msgid)
void ED_area_status_text(ScrArea *area, const char *str)
Definition area.cc:803
#define UI_MAX_DRAW_STR
#define str(s)
char text[50]
Definition transform.hh:347
eTConstraint mode
Definition transform.hh:351
float center_local[3]
Definition transform.hh:475
float smtx[3][3]
float axismtx[3][3]
float mtx[3][3]
TransDataExtension * ext
short around
Definition transform.hh:580
float spacemtx_inv[3][3]
Definition transform.hh:593
float values[4]
Definition transform.hh:624
eTFlag flag
Definition transform.hh:523
MouseInput mouse
Definition transform.hh:543
float values_final[4]
Definition transform.hh:632
TransCon con
Definition transform.hh:534
float spacemtx[3][3]
Definition transform.hh:592
eTContext options
Definition transform.hh:521
ScrArea * area
Definition transform.hh:651
@ INPUT_NONE
Definition transform.hh:741
@ CON_APPLY
Definition transform.hh:193
@ CON_AXIS1
Definition transform.hh:196
@ CON_AXIS0
Definition transform.hh:195
@ CON_AXIS2
Definition transform.hh:197
@ CTX_MOVIECLIP
Definition transform.hh:70
@ CTX_POSE_BONE
Definition transform.hh:73
@ CTX_OBJECT
Definition transform.hh:71
@ T_V3D_ALIGN
Definition transform.hh:102
@ T_2D_EDIT
Definition transform.hh:104
@ T_POINTS
Definition transform.hh:93
@ T_NULL_ONE
Definition transform.hh:96
@ T_EDIT
Definition transform.hh:91
void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode)
#define FOREACH_TRANS_DATA_CONTAINER(t, th)
Definition transform.hh:854
void recalc_data(TransInfo *t)
conversion and adaptation of different datablocks to a common struct.
@ TD_INDIVIDUAL_SCALE
@ TD_SKIP
@ TD_NO_LOC
void protectedTransBits(short protectflag, float vec[3])
bool transdata_check_local_center(const TransInfo *t, short around)
void ElementRotation_ex(const TransInfo *t, const TransDataContainer *tc, TransData *td, const float mat[3][3], const float *center)
void constraintSizeLim(const TransInfo *t, const TransDataContainer *tc, TransData *td)
void protectedSizeBits(short protectflag, float size[3])
void constraintTransLim(const TransInfo *t, const TransDataContainer *tc, TransData *td)
transform modes used by different operators.
static void applyMirror(TransInfo *t)
static void ElementMirror(TransInfo *t, TransDataContainer *tc, TransData *td, int axis, bool flip)
static void initMirror(TransInfo *t, wmOperator *)
TransModeInfo TransMode_mirror