Blender  V3.3
transform_mode_mirror.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2001-2002 NaN Holding BV. All rights reserved. */
3 
8 #include <stdlib.h>
9 
10 #include "BLI_math.h"
11 #include "BLI_math_bits.h"
12 #include "BLI_string.h"
13 
14 #include "BKE_armature.h"
15 #include "BKE_context.h"
16 
17 #include "ED_screen.h"
18 
19 #include "UI_interface.h"
20 
21 #include "BLT_translation.h"
22 
23 #include "transform.h"
24 #include "transform_convert.h"
25 
26 #include "transform_mode.h"
27 
28 /* -------------------------------------------------------------------- */
41 static void ElementMirror(TransInfo *t, TransDataContainer *tc, TransData *td, int axis, bool flip)
42 {
43  if ((t->flag & T_V3D_ALIGN) == 0 && td->ext) {
44  /* Size checked needed since the 3D cursor only uses rotation fields. */
45  if (td->ext->size) {
46  float fsize[] = {1.0, 1.0, 1.0};
47 
48  if (axis >= 0) {
49  fsize[axis] = -fsize[axis];
50  }
51  if (flip) {
52  negate_v3(fsize);
53  }
54 
55  protectedSizeBits(td->protectflag, fsize);
56 
57  mul_v3_v3v3(td->ext->size, td->ext->isize, fsize);
58 
59  constraintSizeLim(t, td);
60  }
61 
62  float rmat[3][3];
63  if (axis >= 0) {
64  float imat[3][3];
65  mul_m3_m3m3(rmat, t->spacemtx_inv, td->axismtx);
66  rmat[axis][0] = -rmat[axis][0];
67  rmat[axis][1] = -rmat[axis][1];
68  rmat[axis][2] = -rmat[axis][2];
69  rmat[0][axis] = -rmat[0][axis];
70  rmat[1][axis] = -rmat[1][axis];
71  rmat[2][axis] = -rmat[2][axis];
72  invert_m3_m3(imat, td->axismtx);
73  mul_m3_m3m3(rmat, rmat, imat);
74  mul_m3_m3m3(rmat, t->spacemtx, rmat);
75 
76  ElementRotation_ex(t, tc, td, rmat, td->center);
77 
78  if (td->ext->rotAngle) {
79  *td->ext->rotAngle = -td->ext->irotAngle;
80  }
81  }
82  else {
83  unit_m3(rmat);
84  ElementRotation_ex(t, tc, td, rmat, td->center);
85 
86  if (td->ext->rotAngle) {
87  *td->ext->rotAngle = td->ext->irotAngle;
88  }
89  }
90  }
91 
92  if ((td->flag & TD_NO_LOC) == 0) {
93  float center[3], vec[3];
94 
95  /* Local constraint shouldn't alter center. */
96  if (transdata_check_local_center(t, t->around)) {
97  copy_v3_v3(center, td->center);
98  }
99  else if (t->options & CTX_MOVIECLIP) {
100  if (td->flag & TD_INDIVIDUAL_SCALE) {
101  copy_v3_v3(center, td->center);
102  }
103  else {
105  }
106  }
107  else {
109  }
110 
111  /* For individual element center, Editmode need to use iloc. */
112  if (t->flag & T_POINTS) {
113  sub_v3_v3v3(vec, td->iloc, center);
114  }
115  else {
116  sub_v3_v3v3(vec, td->center, center);
117  }
118 
119  if (axis >= 0) {
120  /* Always do the mirror in global space. */
121  if (t->flag & T_EDIT) {
122  mul_m3_v3(td->mtx, vec);
123  }
124  reflect_v3_v3v3(vec, vec, t->spacemtx[axis]);
125  if (t->flag & T_EDIT) {
126  mul_m3_v3(td->smtx, vec);
127  }
128  }
129  if (flip) {
130  negate_v3(vec);
131  }
132 
133  add_v3_v3(vec, center);
134  if (t->flag & T_POINTS) {
135  sub_v3_v3(vec, td->iloc);
136  }
137  else {
138  sub_v3_v3(vec, td->center);
139  }
140 
141  if (t->options & (CTX_OBJECT | CTX_POSE_BONE)) {
142  mul_m3_v3(td->smtx, vec);
143  }
144 
146  if (td->loc) {
147  add_v3_v3v3(td->loc, td->iloc, vec);
148  }
149 
150  constraintTransLim(t, td);
151  }
152 }
153 
154 static void applyMirror(TransInfo *t, const int UNUSED(mval[2]))
155 {
156  int i;
157  char str[UI_MAX_DRAW_STR];
158  copy_v3_v3(t->values_final, t->values);
159 
160  /* OPTIMIZATION:
161  * This still recalculates transformation on mouse move
162  * while it should only recalculate on constraint change. */
163 
164  /* if an axis has been selected */
165  if (t->con.mode & CON_APPLY) {
166  /* #special_axis is either the constraint plane normal or the constraint axis.
167  * Assuming that CON_AXIS0 < CON_AXIS1 < CON_AXIS2 and CON_AXIS2 is CON_AXIS0 << 2 */
168  BLI_assert(CON_AXIS2 == CON_AXIS0 << 2);
169  int axis_bitmap = (t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2)) / CON_AXIS0;
170  int special_axis_bitmap = 0;
171  int special_axis = -1;
172  int bitmap_len = count_bits_i(axis_bitmap);
173  if (LIKELY(!ELEM(bitmap_len, 0, 3))) {
174  special_axis_bitmap = (bitmap_len == 2) ? ~axis_bitmap : axis_bitmap;
175  special_axis = bitscan_forward_i(special_axis_bitmap);
176  }
177 
178  BLI_snprintf(str, sizeof(str), TIP_("Mirror%s"), t->con.text);
179 
181  TransData *td = tc->data;
182  for (i = 0; i < tc->data_len; i++, td++) {
183  if (td->flag & TD_SKIP) {
184  continue;
185  }
186 
187  ElementMirror(t, tc, td, special_axis, bitmap_len >= 2);
188  }
189  }
190 
191  recalcData(t);
192 
193  ED_area_status_text(t->area, str);
194  }
195  else {
197  TransData *td = tc->data;
198  for (i = 0; i < tc->data_len; i++, td++) {
199  if (td->flag & TD_SKIP) {
200  continue;
201  }
202 
203  ElementMirror(t, tc, td, -1, false);
204  }
205  }
206 
207  recalcData(t);
208 
209  if (t->flag & T_2D_EDIT) {
210  ED_area_status_text(t->area, TIP_("Select a mirror axis (X, Y)"));
211  }
212  else {
213  ED_area_status_text(t->area, TIP_("Select a mirror axis (X, Y, Z)"));
214  }
215  }
216 }
217 
219 {
220  t->transform = applyMirror;
221  initMouseInputMode(t, &t->mouse, INPUT_NONE);
222 
223  t->flag |= T_NULL_ONE;
224 }
225 
#define BLI_assert(a)
Definition: BLI_assert.h:46
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])
Definition: math_matrix.c:926
void unit_m3(float m[3][3])
Definition: math_matrix.c:40
bool invert_m3_m3(float R[3][3], const float A[3][3])
Definition: math_matrix.c:1180
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
Definition: math_matrix.c:388
void reflect_v3_v3v3(float out[3], const float vec[3], const float normal[3])
Definition: math_vector.c:691
MINLINE void mul_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void sub_v3_v3(float r[3], const float a[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 add_v3_v3(float r[3], const float a[3])
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
#define UNUSED(x)
#define ELEM(...)
#define LIKELY(x)
#define TIP_(msgid)
void ED_area_status_text(ScrArea *area, const char *str)
Definition: area.c:792
NSNotificationCenter * center
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
#define UI_MAX_DRAW_STR
Definition: UI_interface.h:91
#define str(s)
void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode)
#define FOREACH_TRANS_DATA_CONTAINER(t, th)
float smtx[3][3]
short protectflag
float axismtx[3][3]
float mtx[3][3]
TransDataExtension * ext
void recalcData(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 constraintTransLim(const TransInfo *t, TransData *td)
void ElementRotation_ex(const TransInfo *t, const TransDataContainer *tc, TransData *td, const float mat[3][3], const float *center)
void constraintSizeLim(const TransInfo *t, TransData *td)
void protectedSizeBits(short protectflag, float size[3])
transform modes used by different operators.
static void ElementMirror(TransInfo *t, TransDataContainer *tc, TransData *td, int axis, bool flip)
static void applyMirror(TransInfo *t, const int UNUSED(mval[2]))
void initMirror(TransInfo *t)