Blender V5.0
transform_mode.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
8
9#include <cstdlib>
10
11#include "DNA_armature_types.h"
13#include "DNA_space_types.h"
15
16#include "BLI_listbase.h"
17#include "BLI_math_base.hh"
18#include "BLI_math_matrix.h"
19#include "BLI_math_rotation.h"
20#include "BLI_math_vector.h"
21#include "BLI_string_utf8.h"
22
23#include "BKE_constraint.h"
24#include "BKE_context.hh"
25
26#include "BLT_translation.hh"
27
28#include "transform.hh"
29#include "transform_convert.hh"
30#include "transform_gizmo.hh"
32#include "transform_snap.hh"
33
34/* Own include. */
35#include "transform_mode.hh"
36
37namespace blender::ed::transform {
38
40{
41 if (mode == TFM_BONESIZE) {
43 BLI_assert(ob);
44 if (ob->type != OB_ARMATURE) {
45 return TFM_RESIZE;
46 }
47 bArmature *arm = static_cast<bArmature *>(ob->data);
48 if (arm->drawtype == ARM_DRAW_TYPE_ENVELOPE) {
50 }
51 }
52
53 return mode;
54}
55
56bool transdata_check_local_center(const TransInfo *t, short around)
57{
58 return ((around == V3D_AROUND_LOCAL_ORIGINS) &&
59 ((t->options & (CTX_OBJECT | CTX_POSE_BONE)) ||
60 /* Implicit: `(t->flag & T_EDIT)`. */
62 OB_MESH,
67 OB_ARMATURE) ||
68 (t->spacetype == SPACE_GRAPH) ||
70}
71
83
85{
86 return (t->flag & T_V3D_ALIGN) && (t->options & CTX_OBJECT) &&
88 (CTX_DATA_COUNT(t->context, selected_editable_objects) == 1);
89}
90
91/* -------------------------------------------------------------------- */
94
95void protectedTransBits(short protectflag, float vec[3])
96{
97 if (protectflag & OB_LOCK_LOCX) {
98 vec[0] = 0.0f;
99 }
100 if (protectflag & OB_LOCK_LOCY) {
101 vec[1] = 0.0f;
102 }
103 if (protectflag & OB_LOCK_LOCZ) {
104 vec[2] = 0.0f;
105 }
106}
107
108/* This function only does the delta rotation. */
109static void protectedQuaternionBits(short protectflag, float quat[4], const float oldquat[4])
110{
111 /* Check that protection flags are set. */
112 if ((protectflag & (OB_LOCK_ROTX | OB_LOCK_ROTY | OB_LOCK_ROTZ | OB_LOCK_ROTW)) == 0) {
113 return;
114 }
115
116 if (protectflag & OB_LOCK_ROT4D) {
117 /* Quaternions getting limited as 4D entities that they are. */
118 if (protectflag & OB_LOCK_ROTW) {
119 quat[0] = oldquat[0];
120 }
121 if (protectflag & OB_LOCK_ROTX) {
122 quat[1] = oldquat[1];
123 }
124 if (protectflag & OB_LOCK_ROTY) {
125 quat[2] = oldquat[2];
126 }
127 if (protectflag & OB_LOCK_ROTZ) {
128 quat[3] = oldquat[3];
129 }
130 }
131 else {
132 /* Quaternions get limited with euler... (compatibility mode). */
133 float eul[3], oldeul[3], nquat[4], noldquat[4];
134 float qlen;
135
136 qlen = normalize_qt_qt(nquat, quat);
137 normalize_qt_qt(noldquat, oldquat);
138
139 quat_to_eul(eul, nquat);
140 quat_to_eul(oldeul, noldquat);
141
142 if (protectflag & OB_LOCK_ROTX) {
143 eul[0] = oldeul[0];
144 }
145 if (protectflag & OB_LOCK_ROTY) {
146 eul[1] = oldeul[1];
147 }
148 if (protectflag & OB_LOCK_ROTZ) {
149 eul[2] = oldeul[2];
150 }
151
152 eul_to_quat(quat, eul);
153
154 /* Restore original quat size. */
155 mul_qt_fl(quat, qlen);
156
157 /* Quaternions flip w sign to accumulate rotations correctly. */
158 if ((nquat[0] < 0.0f && quat[0] > 0.0f) || (nquat[0] > 0.0f && quat[0] < 0.0f)) {
159 mul_qt_fl(quat, -1.0f);
160 }
161 }
162}
163
164static void protectedRotateBits(short protectflag, float eul[3], const float oldeul[3])
165{
166 if (protectflag & OB_LOCK_ROTX) {
167 eul[0] = oldeul[0];
168 }
169 if (protectflag & OB_LOCK_ROTY) {
170 eul[1] = oldeul[1];
171 }
172 if (protectflag & OB_LOCK_ROTZ) {
173 eul[2] = oldeul[2];
174 }
175}
176
182 short protectflag, float axis[3], float *angle, const float oldAxis[3], float oldAngle)
183{
184 /* Check that protection flags are set. */
185 if ((protectflag & (OB_LOCK_ROTX | OB_LOCK_ROTY | OB_LOCK_ROTZ | OB_LOCK_ROTW)) == 0) {
186 return;
187 }
188
189 if (protectflag & OB_LOCK_ROT4D) {
190 /* Axis-angle getting limited as 4D entities that they are... */
191 if (protectflag & OB_LOCK_ROTW) {
192 *angle = oldAngle;
193 }
194 if (protectflag & OB_LOCK_ROTX) {
195 axis[0] = oldAxis[0];
196 }
197 if (protectflag & OB_LOCK_ROTY) {
198 axis[1] = oldAxis[1];
199 }
200 if (protectflag & OB_LOCK_ROTZ) {
201 axis[2] = oldAxis[2];
202 }
203 }
204 else {
205 /* Axis-angle get limited with euler. */
206 float eul[3], oldeul[3];
207
209 axis_angle_to_eulO(oldeul, EULER_ORDER_DEFAULT, oldAxis, oldAngle);
210
211 if (protectflag & OB_LOCK_ROTX) {
212 eul[0] = oldeul[0];
213 }
214 if (protectflag & OB_LOCK_ROTY) {
215 eul[1] = oldeul[1];
216 }
217 if (protectflag & OB_LOCK_ROTZ) {
218 eul[2] = oldeul[2];
219 }
220
222
223 /* When converting to axis-angle,
224 * we need a special exception for the case when there is no axis. */
225 if (IS_EQF(axis[0], axis[1]) && IS_EQF(axis[1], axis[2])) {
226 /* For now, rotate around y-axis then (so that it simply becomes the roll). */
227 axis[1] = 1.0f;
228 }
229 }
230}
231
232void protectedScaleBits(short protectflag, float scale[3])
233{
234 if (protectflag & OB_LOCK_SCALEX) {
235 scale[0] = 1.0f;
236 }
237 if (protectflag & OB_LOCK_SCALEY) {
238 scale[1] = 1.0f;
239 }
240 if (protectflag & OB_LOCK_SCALEZ) {
241 scale[2] = 1.0f;
242 }
243}
244
246
247/* -------------------------------------------------------------------- */
250
252{
253 if (td->con) {
258
259 bConstraintOb cob = {nullptr};
260 bConstraint *con;
261 float ctime = float(t->scene->r.cfra);
262
263 /* Make a temporary bConstraintOb for using these limit constraints
264 * - They only care that cob->matrix is correctly set ;-).
265 * - Current space should be local.
266 */
267 unit_m4(cob.matrix);
268 copy_v3_v3(cob.matrix[3], td->loc);
269
270 /* Evaluate valid constraints. */
271 for (con = td->con; con; con = con->next) {
272 const bConstraintTypeInfo *cti = nullptr;
273 ListBase targets = {nullptr, nullptr};
274
275 /* Only consider constraint if enabled. */
276 if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) {
277 continue;
278 }
279 if (con->enforce == 0.0f) {
280 continue;
281 }
282
283 /* Only use it if it's tagged for this purpose (and the right type). */
284 if (con->type == CONSTRAINT_TYPE_LOCLIMIT) {
286
287 if ((data->flag2 & LIMIT_TRANSFORM) == 0) {
288 continue;
289 }
290 cti = ctiLoc;
291 }
292 else if (con->type == CONSTRAINT_TYPE_DISTLIMIT) {
294
295 if ((data->flag & LIMITDIST_TRANSFORM) == 0) {
296 continue;
297 }
298 cti = ctiDist;
299 }
300
301 if (cti) {
302 /* Do space conversions. */
303 if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
304 mul_m3_v3(td->mtx, cob.matrix[3]);
305 if (tc->use_local_mat) {
306 add_v3_v3(cob.matrix[3], tc->mat[3]);
307 }
308 }
309 else if (con->ownspace == CONSTRAINT_SPACE_POSE) {
310 /* Bone space without considering object transformations. */
311 mul_m3_v3(td->mtx, cob.matrix[3]);
312 mul_m3_v3(tc->imat3, cob.matrix[3]);
313 }
314 else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) {
315 /* Skip... incompatible spacetype. */
316 continue;
317 }
318
319 /* Initialize the custom space for use in calculating the matrices. */
321
322 /* Get constraint targets if needed. */
323 BKE_constraint_targets_for_solving_get(t->depsgraph, con, &cob, &targets, ctime);
324
325 /* Do constraint. */
326 cti->evaluate_constraint(con, &cob, &targets);
327
328 /* Convert spaces again. */
329 if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
330 if (tc->use_local_mat) {
331 sub_v3_v3(cob.matrix[3], tc->mat[3]);
332 }
333 mul_m3_v3(td->smtx, cob.matrix[3]);
334 }
335 else if (con->ownspace == CONSTRAINT_SPACE_POSE) {
336 mul_m3_v3(tc->mat3, cob.matrix[3]);
337 mul_m3_v3(td->smtx, cob.matrix[3]);
338 }
339
340 /* Free targets list. */
341 BLI_freelistN(&targets);
342 }
343 }
344
345 /* Copy results from `cob->matrix`. */
346 copy_v3_v3(td->loc, cob.matrix[3]);
347 }
348}
349
351{
352 /* Make a temporary bConstraintOb for use by limit constraints
353 * - they only care that cob->matrix is correctly set ;-)
354 * - current space should be local
355 */
356 memset(cob, 0, sizeof(bConstraintOb));
357 if (!td_ext) {
358 return;
359 }
360 if (td_ext->rotOrder == ROT_MODE_QUAT) {
361 /* Quaternion. */
362 /* Objects and bones do normalization first too, otherwise
363 * we don't necessarily end up with a rotation matrix, and
364 * then conversion back to quat gives a different result. */
365 float quat[4];
366 normalize_qt_qt(quat, td_ext->quat);
367 quat_to_mat4(cob->matrix, quat);
368 }
369 else if (td_ext->rotOrder == ROT_MODE_AXISANGLE) {
370 /* Axis angle. */
371 axis_angle_to_mat4(cob->matrix, td_ext->rotAxis, *td_ext->rotAngle);
372 }
373 else {
374 /* Eulers. */
375 eulO_to_mat4(cob->matrix, td_ext->rot, td_ext->rotOrder);
376 }
377}
378
379static void constraintRotLim(const TransInfo * /*t*/, TransData *td, TransDataExtension *td_ext)
380{
381 if (td->con) {
383 bConstraintOb cob;
384 bConstraint *con;
385 bool do_limit = false;
386
387 /* Evaluate valid constraints. */
388 for (con = td->con; con; con = con->next) {
389 /* Only consider constraint if enabled. */
390 if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) {
391 continue;
392 }
393 if (con->enforce == 0.0f) {
394 continue;
395 }
396
397 /* We're only interested in Limit-Rotation constraints. */
398 if (con->type == CONSTRAINT_TYPE_ROTLIMIT) {
400
401 /* Only use it if it's tagged for this purpose. */
402 if ((data->flag2 & LIMIT_TRANSFORM) == 0) {
403 continue;
404 }
405
406 /* Skip incompatible space-types. */
408 continue;
409 }
410
411 /* Only do conversion if necessary, to preserve quaternion and euler rotations. */
412 if (do_limit == false) {
413 constraintob_from_transdata(&cob, td_ext);
414 do_limit = true;
415 }
416
417 /* Do space conversions. */
418 if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
419 /* Just multiply by `td->mtx` (this should be ok). */
420 mul_m4_m3m4(cob.matrix, td->mtx, cob.matrix);
421 }
422
423 /* Do constraint. */
424 cti->evaluate_constraint(con, &cob, nullptr);
425
426 /* Convert spaces again. */
427 if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
428 /* Just multiply by `td->smtx` (this should be ok). */
429 mul_m4_m3m4(cob.matrix, td->smtx, cob.matrix);
430 }
431 }
432 }
433
434 if (do_limit) {
435 /* Copy results from `cob->matrix`. */
436 if (td_ext->rotOrder == ROT_MODE_QUAT) {
437 /* Quaternion. */
438 mat4_to_quat(td_ext->quat, cob.matrix);
439 }
440 else if (td_ext->rotOrder == ROT_MODE_AXISANGLE) {
441 /* Axis angle. */
442 mat4_to_axis_angle(td_ext->rotAxis, td_ext->rotAngle, cob.matrix);
443 }
444 else {
445 /* Eulers. */
446 mat4_to_eulO(td_ext->rot, td_ext->rotOrder, cob.matrix);
447 }
448 }
449 }
450}
451
452void constraintScaleLim(const TransInfo *t, const TransDataContainer *tc, int td_index)
453{
454 if (!tc->data_ext) {
455 return;
456 }
457
458 TransData *td = &tc->data[td_index];
459 if (!td->con) {
460 return;
461 }
462
463 /* Make a temporary bConstraintOb for using these limit constraints
464 * - they only care that cob->matrix is correctly set ;-)
465 * - current space should be local
466 */
467 if ((td->flag & TD_SINGLE_SCALE) && !(t->con.mode & CON_APPLY)) {
468 /* Scale val and reset the "scale". */
469 return; /* TODO: fix this case. */
470 }
471
472 /* Reset val if SINGLESIZE but using a constraint. */
473 if (td->flag & TD_SINGLE_SCALE) {
474 return;
475 }
476
478 bConstraintOb cob = {nullptr};
479 bConstraint *con;
480 float scale_sign[3], scale_abs[3];
481 int i;
482
483 TransDataExtension *td_ext = &tc->data_ext[td_index];
484
485 /* Separate out sign to apply back later. */
486 for (i = 0; i < 3; i++) {
487 scale_sign[i] = signf(td_ext->scale[i]);
488 scale_abs[i] = fabsf(td_ext->scale[i]);
489 }
490
491 size_to_mat4(cob.matrix, scale_abs);
492
493 /* Evaluate valid constraints. */
494 for (con = td->con; con; con = con->next) {
495 /* Only consider constraint if enabled. */
496 if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) {
497 continue;
498 }
499 if (con->enforce == 0.0f) {
500 continue;
501 }
502
503 /* We're only interested in Limit-Scale constraints. */
504 if (con->type == CONSTRAINT_TYPE_SIZELIMIT) {
505 bSizeLimitConstraint *data = static_cast<bSizeLimitConstraint *>(con->data);
506
507 /* Only use it if it's tagged for this purpose. */
508 if ((data->flag2 & LIMIT_TRANSFORM) == 0) {
509 continue;
510 }
511
512 /* Do space conversions. */
513 if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
514 /* Just multiply by `td->mtx` (this should be ok). */
515 mul_m4_m3m4(cob.matrix, td->mtx, cob.matrix);
516 }
517 else if (con->ownspace == CONSTRAINT_SPACE_POSE) {
518 /* Bone space without considering object transformations. */
519 mul_m4_m3m4(cob.matrix, td->mtx, cob.matrix);
520 mul_m4_m3m4(cob.matrix, tc->imat3, cob.matrix);
521 }
522 else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) {
523 /* Skip... incompatible `spacetype`. */
524 continue;
525 }
526
527 /* Do constraint. */
528 cti->evaluate_constraint(con, &cob, nullptr);
529
530 /* Convert spaces again. */
531 if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
532 /* Just multiply by `td->smtx` (this should be ok). */
533 mul_m4_m3m4(cob.matrix, td->smtx, cob.matrix);
534 }
535 else if (con->ownspace == CONSTRAINT_SPACE_POSE) {
536 mul_m4_m3m4(cob.matrix, tc->mat3, cob.matrix);
537 mul_m4_m3m4(cob.matrix, td->smtx, cob.matrix);
538 }
539 }
540 }
541
542 /* Copy results from `cob->matrix`. */
543 if ((td->flag & TD_SINGLE_SCALE) && !(t->con.mode & CON_APPLY)) {
544 /* Scale val and reset the "scale". */
545 return; /* TODO: fix this case. */
546 }
547
548 /* Reset val if SINGLESIZE but using a constraint. */
549 if (td->flag & TD_SINGLE_SCALE) {
550 return;
551 }
552
553 /* Extract scale from matrix and apply back sign. */
554 mat4_to_size(td_ext->scale, cob.matrix);
555 mul_v3_v3(td_ext->scale, scale_sign);
556}
557
559
560/* -------------------------------------------------------------------- */
563
564void headerRotation(TransInfo *t, char *str, const int str_size, float final)
565{
566 size_t ofs = 0;
567
568 if (hasNumInput(&t->num)) {
569 char c[NUM_STR_REP_LEN];
570
571 outputNumInput(&(t->num), c, t->scene->unit);
572
574 str + ofs, str_size - ofs, IFACE_("Rotation: %s %s %s"), &c[0], t->con.text, t->proptext);
575 }
576 else {
577 ofs += BLI_snprintf_utf8_rlen(str + ofs,
578 str_size - ofs,
579 IFACE_("Rotation: %.2f%s %s"),
580 RAD2DEGF(final),
581 t->con.text,
582 t->proptext);
583 }
584
585 if (t->flag & T_PROP_EDIT_ALL) {
587 str + ofs, str_size - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size);
588 }
589}
590
592 const TransDataContainer *tc,
593 TransData *td,
594 TransDataExtension *td_ext,
595 const float mat[3][3],
596 const float *center)
597{
598 float vec[3], totmat[3][3], smat[3][3];
599 float eul[3], fmat[3][3], quat[4];
600
601 if (t->flag & T_POINTS) {
602 mul_m3_m3m3(totmat, mat, td->mtx);
603 mul_m3_m3m3(smat, td->smtx, totmat);
604
605 /* Apply gpencil falloff. */
606 if (t->options & CTX_GPENCIL_STROKES) {
607 if (t->obedit_type == OB_GREASE_PENCIL) {
608 const float *gp_falloff = static_cast<const float *>(td->extra);
609 if (gp_falloff != nullptr && *gp_falloff != 1.0f) {
610 float ident_mat[3][3];
611 unit_m3(ident_mat);
612 interp_m3_m3m3(smat, ident_mat, smat, *gp_falloff);
613 }
614 }
615 }
616
617 sub_v3_v3v3(vec, td->iloc, center);
618 mul_m3_v3(smat, vec);
619
620 add_v3_v3v3(td->loc, vec, center);
621
622 sub_v3_v3v3(vec, td->loc, td->iloc);
624 add_v3_v3v3(td->loc, td->iloc, vec);
625
626 if (td->flag & TD_USEQUAT) {
627 mul_m3_series(fmat, td->smtx, mat, td->mtx);
628 mat3_to_quat(quat, fmat); /* Actual transform. */
629
630 if (td_ext->quat) {
631 mul_qt_qtqt(td_ext->quat, quat, td_ext->iquat);
632
633 /* Is there a reason not to have this here? -jahka. */
634 protectedQuaternionBits(td->protectflag, td_ext->quat, td_ext->iquat);
635 }
636 }
637 }
650 else if (t->options & CTX_POSE_BONE) {
651 /* Extract and invert armature object matrix. */
652
653 if ((td->flag & TD_NO_LOC) == 0) {
654 sub_v3_v3v3(vec, td_ext->center_no_override, center);
655
656 mul_m3_v3(tc->mat3, vec); /* To Global space. */
657 mul_m3_v3(mat, vec); /* Applying rotation. */
658 mul_m3_v3(tc->imat3, vec); /* To Local space. */
659
660 add_v3_v3(vec, center);
661 /* `vec` now is the location where the object has to be. */
662
663 /* Translation needed from the initial location. */
664 sub_v3_v3v3(vec, vec, td_ext->center_no_override);
665
666 /* Special exception, see TD_PBONE_LOCAL_MTX definition comments. */
667 if (td->flag & TD_PBONE_LOCAL_MTX_P) {
668 /* Do nothing. */
669 }
670 else if (td->flag & TD_PBONE_LOCAL_MTX_C) {
671 mul_m3_v3(tc->mat3, vec); /* To Global space. */
672 mul_m3_v3(td_ext->l_smtx, vec); /* To Pose space (Local Location). */
673 }
674 else {
675 mul_m3_v3(tc->mat3, vec); /* To Global space. */
676 mul_m3_v3(td->smtx, vec); /* To Pose space. */
677 }
678
680
681 add_v3_v3v3(td->loc, td->iloc, vec);
682
683 constraintTransLim(t, tc, td);
684 }
685
686 /* Rotation. */
687 /* MORE HACK: as in some cases the matrix to apply location and rot/scale is not the same,
688 * and ElementRotation() might be called in Translation context (with align snapping),
689 * we need to be sure to actually use the *rotation* matrix here...
690 * So no other way than storing it in some dedicated members of `td_ext`! */
691 if ((t->flag & T_V3D_ALIGN) == 0) { /* Align mode doesn't rotate objects itself. */
692 /* Euler or quaternion/axis-angle? */
693 if (td_ext->rotOrder == ROT_MODE_QUAT) {
694 mul_m3_series(fmat, td_ext->r_smtx, mat, td_ext->r_mtx);
695
696 mat3_to_quat(quat, fmat); /* Actual transform. */
697
698 mul_qt_qtqt(td_ext->quat, quat, td_ext->iquat);
699 /* This function works on end result. */
700 protectedQuaternionBits(td->protectflag, td_ext->quat, td_ext->iquat);
701 }
702 else if (td_ext->rotOrder == ROT_MODE_AXISANGLE) {
703 /* Calculate effect based on quaternions. */
704 float iquat[4], tquat[4];
705
706 axis_angle_to_quat(iquat, td_ext->irotAxis, td_ext->irotAngle);
707
708 mul_m3_series(fmat, td_ext->r_smtx, mat, td_ext->r_mtx);
709 mat3_to_quat(quat, fmat); /* Actual transform. */
710 mul_qt_qtqt(tquat, quat, iquat);
711
712 quat_to_axis_angle(td_ext->rotAxis, td_ext->rotAngle, tquat);
713
714 /* This function works on end result. */
716 td_ext->rotAxis,
717 td_ext->rotAngle,
718 td_ext->irotAxis,
719 td_ext->irotAngle);
720 }
721 else {
722 float eulmat[3][3];
723
724 mul_m3_m3m3(totmat, mat, td_ext->r_mtx);
725 mul_m3_m3m3(smat, td_ext->r_smtx, totmat);
726
727 /* Calculate the total rotation in eulers. */
728 copy_v3_v3(eul, td_ext->irot);
729 eulO_to_mat3(eulmat, eul, td_ext->rotOrder);
730
731 /* `mat = transform`, `obmat = bone rotation`. */
732 mul_m3_m3m3(fmat, smat, eulmat);
733
734 mat3_to_compatible_eulO(eul, td_ext->rot, td_ext->rotOrder, fmat);
735
736 /* And apply (to end result only). */
737 protectedRotateBits(td->protectflag, eul, td_ext->irot);
738 copy_v3_v3(td_ext->rot, eul);
739 }
740
741 constraintRotLim(t, td, td_ext);
742 }
743 }
744 else {
745 if ((td->flag & TD_NO_LOC) == 0) {
746 /* Translation. */
747 sub_v3_v3v3(vec, td->center, center);
748 mul_m3_v3(mat, vec);
749 add_v3_v3(vec, center);
750 /* `vec` now is the location where the object has to be. */
751 sub_v3_v3(vec, td->center);
752 mul_m3_v3(td->smtx, vec);
753
755
756 add_v3_v3v3(td->loc, td->iloc, vec);
757 }
758
759 constraintTransLim(t, tc, td);
760
761 /* Rotation. */
762 if ((t->flag & T_V3D_ALIGN) == 0) { /* Align mode doesn't rotate objects itself. */
763 /* Euler or quaternion? */
764 if ((td_ext->rotOrder == ROT_MODE_QUAT) || (td->flag & TD_USEQUAT)) {
765 /* Can be called for texture space translate for example, then opt out. */
766 if (td_ext->quat) {
767 mul_m3_series(fmat, td->smtx, mat, td->mtx);
768
769 if (!is_zero_v3(td_ext->dquat)) {
770 /* Correct for delta quat. */
771 float tmp_mat[3][3];
772 quat_to_mat3(tmp_mat, td_ext->dquat);
773 mul_m3_m3m3(fmat, fmat, tmp_mat);
774 }
775
776 mat3_to_quat(quat, fmat); /* Actual transform. */
777
778 if (!is_zero_v4(td_ext->dquat)) {
779 /* Correct back for delta quaternion. */
780 float idquat[4];
781 invert_qt_qt_normalized(idquat, td_ext->dquat);
782 mul_qt_qtqt(quat, idquat, quat);
783 }
784
785 mul_qt_qtqt(td_ext->quat, quat, td_ext->iquat);
786
787 /* This function works on end result. */
788 protectedQuaternionBits(td->protectflag, td_ext->quat, td_ext->iquat);
789 }
790 }
791 else if (td_ext->rotOrder == ROT_MODE_AXISANGLE) {
792 /* Calculate effect based on quaternions. */
793 float iquat[4], tquat[4];
794
795 axis_angle_to_quat(iquat, td_ext->irotAxis, td_ext->irotAngle);
796
797 mul_m3_series(fmat, td->smtx, mat, td->mtx);
798 mat3_to_quat(quat, fmat); /* Actual transform. */
799 mul_qt_qtqt(tquat, quat, iquat);
800
801 quat_to_axis_angle(td_ext->rotAxis, td_ext->rotAngle, tquat);
802
803 /* This function works on end result. */
805 td_ext->rotAxis,
806 td_ext->rotAngle,
807 td_ext->irotAxis,
808 td_ext->irotAngle);
809 }
810 else {
811 /* Calculate the total rotation in eulers. */
812 float obmat[3][3];
813
814 mul_m3_m3m3(totmat, mat, td->mtx);
815 mul_m3_m3m3(smat, td->smtx, totmat);
816
817 if (!is_zero_v3(td_ext->drot)) {
818 /* Correct for delta rot. */
819 add_eul_euleul(eul, td_ext->irot, td_ext->drot, td_ext->rotOrder);
820 }
821 else {
822 copy_v3_v3(eul, td_ext->irot);
823 }
824
825 eulO_to_mat3(obmat, eul, td_ext->rotOrder);
826 mul_m3_m3m3(fmat, smat, obmat);
827 mat3_to_compatible_eulO(eul, td_ext->rot, td_ext->rotOrder, fmat);
828
829 if (!is_zero_v3(td_ext->drot)) {
830 /* Correct back for delta rot. */
831 sub_eul_euleul(eul, eul, td_ext->drot, td_ext->rotOrder);
832 }
833
834 /* And apply. */
835 protectedRotateBits(td->protectflag, eul, td_ext->irot);
836 copy_v3_v3(td_ext->rot, eul);
837 }
838
839 constraintRotLim(t, td, td_ext);
840 }
841 }
842}
843
845 const TransDataContainer *tc,
846 TransData *td,
847 TransDataExtension *td_ext,
848 const float mat[3][3],
849 const short around)
850{
851 const float *center;
852
853 /* Local constraint shouldn't alter center. */
854 if (transdata_check_local_center(t, around)) {
855 center = td->center;
856 }
857 else {
858 center = tc->center_local;
859 }
860
861 ElementRotation_ex(t, tc, td, td_ext, mat, center);
862}
863
865
866/* -------------------------------------------------------------------- */
869
870void headerResize(TransInfo *t, const float vec[3], char *str, const int str_size)
871{
872 char tvec[NUM_STR_REP_LEN * 3];
873 size_t ofs = 0;
874 if (hasNumInput(&t->num)) {
875 outputNumInput(&(t->num), tvec, t->scene->unit);
876 }
877 else {
878 BLI_snprintf_utf8(&tvec[0], NUM_STR_REP_LEN, "%.4f", vec[0]);
879 BLI_snprintf_utf8(&tvec[NUM_STR_REP_LEN], NUM_STR_REP_LEN, "%.4f", vec[1]);
880 BLI_snprintf_utf8(&tvec[NUM_STR_REP_LEN * 2], NUM_STR_REP_LEN, "%.4f", vec[2]);
881 }
882
883 if (t->con.mode & CON_APPLY) {
884 switch (t->num.idx_max) {
885 case 0:
886 ofs += BLI_snprintf_utf8_rlen(str + ofs,
887 str_size - ofs,
888 IFACE_("Scale: %s%s %s"),
889 &tvec[0],
890 t->con.text,
891 t->proptext);
892 break;
893 case 1:
894 ofs += BLI_snprintf_utf8_rlen(str + ofs,
895 str_size - ofs,
896 IFACE_("Scale: %s : %s%s %s"),
897 &tvec[0],
898 &tvec[NUM_STR_REP_LEN],
899 t->con.text,
900 t->proptext);
901 break;
902 case 2:
903 ofs += BLI_snprintf_utf8_rlen(str + ofs,
904 str_size - ofs,
905 IFACE_("Scale: %s : %s : %s%s %s"),
906 &tvec[0],
907 &tvec[NUM_STR_REP_LEN],
908 &tvec[NUM_STR_REP_LEN * 2],
909 t->con.text,
910 t->proptext);
911 break;
912 }
913 }
914 else {
915 if (t->flag & T_2D_EDIT) {
916 ofs += BLI_snprintf_utf8_rlen(str + ofs,
917 str_size - ofs,
918 IFACE_("Scale X: %s Y: %s%s %s"),
919 &tvec[0],
920 &tvec[NUM_STR_REP_LEN],
921 t->con.text,
922 t->proptext);
923 }
924 else {
925 ofs += BLI_snprintf_utf8_rlen(str + ofs,
926 str_size - ofs,
927 IFACE_("Scale X: %s Y: %s Z: %s%s %s"),
928 &tvec[0],
929 &tvec[NUM_STR_REP_LEN],
930 &tvec[NUM_STR_REP_LEN * 2],
931 t->con.text,
932 t->proptext);
933 }
934 }
935
936 if (t->flag & T_PROP_EDIT_ALL) {
938 str + ofs, str_size - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size);
939 }
940}
941
947static void TransMat3ToSize(const float mat[3][3], const float smat[3][3], float size[3])
948{
949 float rmat[3][3];
950
951 mat3_to_rot_size(rmat, size, mat);
952
953 /* First tried with dot-product... but the sign flip is crucial. */
954 if (dot_v3v3(rmat[0], smat[0]) < 0.0f) {
955 size[0] = -size[0];
956 }
957 if (dot_v3v3(rmat[1], smat[1]) < 0.0f) {
958 size[1] = -size[1];
959 }
960 if (dot_v3v3(rmat[2], smat[2]) < 0.0f) {
961 size[2] = -size[2];
962 }
963}
964
966 const TransDataContainer *tc,
967 int td_index,
968 const float mat[3][3])
969{
970 TransData *td = &tc->data[td_index];
971
972 float tmat[3][3], smat[3][3], center[3];
973 float vec[3];
974
975 if (t->flag & T_EDIT) {
976 mul_m3_m3m3(smat, mat, td->mtx);
977 mul_m3_m3m3(tmat, td->smtx, smat);
978 }
979 else {
980 copy_m3_m3(tmat, mat);
981 }
982
983 if (t->con.applySize) {
984 t->con.applySize(t, tc, td, tmat);
985 }
986
987 /* Local constraint shouldn't alter center. */
989 copy_v3_v3(center, td->center);
990 }
991 else if (t->options & CTX_MOVIECLIP) {
992 if (td->flag & TD_INDIVIDUAL_SCALE) {
993 copy_v3_v3(center, td->center);
994 }
995 else {
996 copy_v3_v3(center, tc->center_local);
997 }
998 }
999 else {
1000 copy_v3_v3(center, tc->center_local);
1001 }
1002
1003 if (tc->data_ext) {
1004 TransDataExtension *td_ext = &tc->data_ext[td_index];
1005
1006 /* Size checked needed since the 3D cursor only uses rotation fields. */
1007 if (td_ext->scale) {
1008 float fscale[3];
1009
1010 if (ELEM(t->data_type,
1015 {
1016 float ob_scale_mat[3][3];
1017 /* Reorient the size mat to fit the oriented object. */
1018 mul_m3_m3m3(ob_scale_mat, tmat, td->axismtx);
1019 // print_m3("ob_scale_mat", ob_scale_mat);
1020 TransMat3ToSize(ob_scale_mat, td->axismtx, fscale);
1021 // print_v3("fscale", fscale);
1022 }
1023 else {
1024 mat3_to_size(fscale, tmat);
1025 }
1026
1027 protectedScaleBits(td->protectflag, fscale);
1028
1029 if ((t->flag & T_V3D_ALIGN) == 0) { /* Align mode doesn't resize objects itself. */
1030 if ((td->flag & TD_SINGLE_SCALE) && !(t->con.mode & CON_APPLY)) {
1031 /* Scale val and reset scale. */
1032 *td->val = td->ival * (1 + (fscale[0] - 1) * td->factor);
1033
1034 td_ext->scale[0] = td_ext->iscale[0];
1035 td_ext->scale[1] = td_ext->iscale[1];
1036 td_ext->scale[2] = td_ext->iscale[2];
1037 }
1038 else {
1039 /* Reset val if #TD_SINGLE_SCALE but using a constraint. */
1040 if (td->flag & TD_SINGLE_SCALE) {
1041 *td->val = td->ival;
1042 }
1043
1044 td_ext->scale[0] = td_ext->iscale[0] * (1 + (fscale[0] - 1) * td->factor);
1045 td_ext->scale[1] = td_ext->iscale[1] * (1 + (fscale[1] - 1) * td->factor);
1046 td_ext->scale[2] = td_ext->iscale[2] * (1 + (fscale[2] - 1) * td->factor);
1047 }
1048 }
1049
1050 constraintScaleLim(t, tc, td_index);
1051 }
1052 }
1053
1054 /* For individual element center, Editmode need to use iloc. */
1055 if (t->flag & T_POINTS) {
1056 sub_v3_v3v3(vec, td->iloc, center);
1057 }
1058 else {
1059 sub_v3_v3v3(vec, td->center, center);
1060 }
1061
1062 mul_m3_v3(tmat, vec);
1063
1064 add_v3_v3(vec, center);
1065 if (t->flag & T_POINTS) {
1066 sub_v3_v3(vec, td->iloc);
1067 }
1068 else {
1069 sub_v3_v3(vec, td->center);
1070 }
1071
1072 /* Grease pencil falloff.
1073 *
1074 * FIXME: This is bad on multiple levels!
1075 *
1076 * - #applyNumInput is not intended to be run for every element,
1077 * this writes back into the number input in a way that doesn't make sense to run many times.
1078 *
1079 * - Writing into #TransInfo should be avoided since it means order of operations
1080 * may impact the result and isn't thread-safe.
1081 *
1082 * Operating on copies as a temporary solution.
1083 */
1084 if (t->options & CTX_GPENCIL_STROKES) {
1085 const float *gp_falloff_ptr = static_cast<const float *>(td->extra);
1086 const float gp_falloff = gp_falloff_ptr != nullptr ? *gp_falloff_ptr : 1.0f;
1087 mul_v3_fl(vec, td->factor * gp_falloff);
1088
1089 /* Scale stroke thickness. */
1090 if (td->val) {
1091 NumInput num_evil = t->num;
1092 float values_final_evil[4];
1093 copy_v4_v4(values_final_evil, t->values_final);
1094 transform_snap_increment(t, values_final_evil);
1095 applyNumInput(&num_evil, values_final_evil);
1096
1097 float ratio = values_final_evil[0];
1098 float transformed_value = td->ival * fabs(ratio);
1099 *td->val = math::max(math::interpolate(td->ival, transformed_value, gp_falloff), 0.001f);
1100 }
1101 }
1102 else {
1103 mul_v3_fl(vec, td->factor);
1104 }
1105
1106 if (t->options & (CTX_OBJECT | CTX_POSE_BONE)) {
1107 if (t->options & CTX_POSE_BONE) {
1108 /* Without this, the resulting location of scaled bones aren't correct,
1109 * especially noticeable scaling root or disconnected bones around the cursor, see #92515. */
1110 mul_mat3_m4_v3(tc->poseobj->object_to_world().ptr(), vec);
1111 }
1112 mul_m3_v3(td->smtx, vec);
1113 }
1114
1116 if (td->loc) {
1117 add_v3_v3v3(td->loc, td->iloc, vec);
1118 }
1119
1120 constraintTransLim(t, tc, td);
1121}
1122
1124
1125/* -------------------------------------------------------------------- */
1128
1129static TransModeInfo *mode_info_get(TransInfo *t, const int mode)
1130{
1131 switch (mode) {
1132 case TFM_TRANSLATION:
1133 return &TransMode_translate;
1134 case TFM_ROTATION:
1135 return &TransMode_rotate;
1136 case TFM_RESIZE:
1137 return &TransMode_resize;
1138 case TFM_SKIN_RESIZE:
1139 return &TransMode_skinresize;
1140 case TFM_TOSPHERE:
1141 return &TransMode_tosphere;
1142 case TFM_SHEAR:
1143 return &TransMode_shear;
1144 case TFM_BEND:
1145 return &TransMode_bend;
1146 case TFM_SHRINKFATTEN:
1147 return &TransMode_shrinkfatten;
1148 case TFM_TILT:
1149 return &TransMode_tilt;
1154 case TFM_TRACKBALL:
1155 return &TransMode_trackball;
1156 case TFM_PUSHPULL:
1157 return &TransMode_pushpull;
1158 case TFM_EDGE_CREASE:
1159 return &TransMode_edgecrease;
1160 case TFM_VERT_CREASE:
1161 return &TransMode_vertcrease;
1162 case TFM_BONESIZE:
1163 return &TransMode_bboneresize;
1164 case TFM_BONE_ENVELOPE:
1166 return &TransMode_boneenvelope;
1167 case TFM_EDGE_SLIDE:
1168 return &TransMode_edgeslide;
1169 case TFM_VERT_SLIDE:
1170 return &TransMode_vertslide;
1171 case TFM_BONE_ROLL:
1172 return &TransMode_boneroll;
1173 case TFM_TIME_TRANSLATE:
1175 case TFM_TIME_SLIDE:
1176 return &TransMode_timeslide;
1177 case TFM_TIME_SCALE:
1178 return &TransMode_timescale;
1179 case TFM_TIME_EXTEND:
1180 /* Do TFM_TIME_TRANSLATE (for most Animation Editors because they have only 1D transforms for
1181 * time values) or TFM_TRANSLATION (for Graph/NLA Editors only since they uses 'standard'
1182 * transforms to get 2D movement) depending on which editor this was called from. */
1183 if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA)) {
1184 return &TransMode_translate;
1185 }
1187 case TFM_BAKE_TIME:
1188 return &TransMode_baketime;
1189 case TFM_MIRROR:
1190 return &TransMode_mirror;
1191 case TFM_BWEIGHT:
1192 return &TransMode_bevelweight;
1193 case TFM_ALIGN:
1194 return &TransMode_align;
1195 case TFM_SEQ_SLIDE:
1196 return &TransMode_seqslide;
1198 return &TransMode_rotatenormal;
1200 return &TransMode_gpopacity;
1201 }
1202 return nullptr;
1203}
1204
1205void transform_mode_init(TransInfo *t, wmOperator *op, const int mode)
1206{
1207 t->mode = eTfmMode(mode);
1208 t->mode_info = mode_info_get(t, mode);
1209
1210 if (t->mode_info) {
1211 t->flag |= eTFlag(t->mode_info->flags);
1212 t->mode_info->init_fn(t, op);
1213 }
1214
1215 if (t->data_type == &TransConvertType_Mesh) {
1216 /* Init Custom Data correction.
1217 * Ideally this should be called when creating the TransData. */
1219 }
1220
1222
1223 /* TODO(@mano-wii): Some of these operations change the `t->mode`.
1224 * This can be bad for Redo. */
1225 // BLI_assert(t->mode == mode);
1226}
1227
1229{
1230 /* Currently only these types are supported. */
1232
1234 return;
1235 }
1236
1237 if (!(t->flag & T_MODAL)) {
1238 return;
1239 }
1240
1241 if (t->orient[O_DEFAULT].type == type) {
1242 return;
1243 }
1244
1245 View3D *v3d = nullptr;
1246 RegionView3D *rv3d = nullptr;
1247 if ((type == V3D_ORIENT_VIEW) && (t->spacetype == SPACE_VIEW3D) && t->region &&
1249 {
1250 v3d = static_cast<View3D *>(t->view);
1251 rv3d = static_cast<RegionView3D *>(t->region->regiondata);
1252 }
1253
1255 t->view_layer,
1256 v3d,
1257 rv3d,
1258 nullptr,
1259 nullptr,
1260 type,
1262 t->orient[O_DEFAULT].matrix);
1263
1264 if (t->orient_curr == O_DEFAULT) {
1265 /* Update Orientation. */
1267 }
1268}
1269
1271{
1272 if ((t->con.mode & CON_APPLY) && t->con.applyRot) {
1273 t->con.applyRot(t, nullptr, nullptr, r_axis);
1274 }
1275 else {
1276 r_axis = t->spacemtx[t->orient_axis];
1277 }
1278}
1279
1281{
1282 float view_vector[3];
1283 view_vector_calc(t, t->center_global, view_vector);
1284 return dot_v3v3(axis, view_vector) > 0.0f;
1285}
1286
1288
1289} // namespace blender::ed::transform
void BKE_constraint_custom_object_space_init(struct bConstraintOb *cob, struct bConstraint *con)
void BKE_constraint_targets_for_solving_get(struct Depsgraph *depsgraph, struct bConstraint *con, struct bConstraintOb *ob, struct ListBase *targets, float ctime)
const bConstraintTypeInfo * BKE_constraint_typeinfo_from_type(int type)
Object * CTX_data_active_object(const bContext *C)
#define CTX_DATA_COUNT(C, member)
#define BLI_assert(a)
Definition BLI_assert.h:46
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:497
MINLINE float signf(float f)
#define RAD2DEGF(_rad)
void mul_m3_v3(const float M[3][3], float r[3])
void copy_m3_m3(float m1[3][3], const float m2[3][3])
void unit_m3(float m[3][3])
void mat3_to_rot_size(float rot[3][3], float size[3], const float mat3[3][3])
void size_to_mat4(float R[4][4], const float size[3])
void interp_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3], float t)
void mat4_to_size(float size[3], const float M[4][4])
#define mul_m3_series(...)
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
void mat3_to_size(float size[3], const float M[3][3])
void mul_m4_m3m4(float R[4][4], const float A[3][3], const float B[4][4])
void mul_mat3_m4_v3(const float mat[4][4], float r[3])
void unit_m4(float m[4][4])
void sub_eul_euleul(float r_eul[3], float a[3], float b[3], short order)
void axis_angle_to_quat(float r[4], const float axis[3], float angle)
void quat_to_mat3(float m[3][3], const float q[4])
@ EULER_ORDER_DEFAULT
void mat3_to_quat(float q[4], const float mat[3][3])
void eulO_to_axis_angle(float axis[3], float *angle, const float eul[3], short order)
void quat_to_mat4(float m[4][4], const float q[4])
void mul_qt_fl(float q[4], float f)
void eul_to_quat(float quat[4], const float eul[3])
void axis_angle_to_mat4(float R[4][4], const float axis[3], float angle)
void eulO_to_mat4(float mat[4][4], const float e[3], short order)
void mat4_to_axis_angle(float axis[3], float *angle, const float mat[4][4])
void quat_to_eul(float eul[3], const float quat[4])
float normalize_qt_qt(float r[4], const float q[4])
void invert_qt_qt_normalized(float q1[4], const float q2[4])
void mat4_to_eulO(float eul[3], short order, const float m[4][4])
void mul_qt_qtqt(float q[4], const float a[4], const float b[4])
void quat_to_axis_angle(float axis[3], float *angle, const float q[4])
void axis_angle_to_eulO(float eul[3], short order, const float axis[3], float angle)
void mat4_to_quat(float q[4], const float mat[4][4])
void mat3_to_compatible_eulO(float eul[3], const float oldrot[3], short order, const float mat[3][3])
void eulO_to_mat3(float M[3][3], const float e[3], short order)
void add_eul_euleul(float r_eul[3], float a[3], float b[3], short order)
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void mul_v3_v3(float r[3], const float a[3])
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE bool is_zero_v4(const float v[4]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE bool is_zero_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_v3_v3(float r[3], const float a[3])
size_t size_t size_t BLI_snprintf_utf8(char *__restrict dst, size_t dst_maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
size_t BLI_snprintf_utf8_rlen(char *__restrict dst, size_t dst_maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
#define ELEM(...)
#define IS_EQF(a, b)
#define IFACE_(msgid)
@ ROT_MODE_QUAT
@ ROT_MODE_AXISANGLE
@ ARM_DRAW_TYPE_ENVELOPE
@ CONSTRAINT_OFF
@ CONSTRAINT_DISABLE
@ CONSTRAINT_TYPE_ROTLIMIT
@ CONSTRAINT_TYPE_DISTLIMIT
@ CONSTRAINT_TYPE_LOCLIMIT
@ CONSTRAINT_TYPE_SIZELIMIT
@ CONSTRAINT_SPACE_POSE
@ CONSTRAINT_SPACE_WORLD
@ CONSTRAINT_SPACE_LOCAL
@ LIMIT_TRANSFORM
@ LIMITDIST_TRANSFORM
@ OB_MBALL
@ OB_GREASE_PENCIL
@ OB_ARMATURE
@ OB_MESH
@ OB_CURVES_LEGACY
@ OB_CURVES
@ OB_LOCK_ROTZ
@ OB_LOCK_ROT4D
@ OB_LOCK_SCALEZ
@ OB_LOCK_ROTX
@ OB_LOCK_SCALEX
@ OB_LOCK_ROTW
@ OB_LOCK_LOCY
@ OB_LOCK_LOCZ
@ OB_LOCK_ROTY
@ OB_LOCK_SCALEY
@ OB_LOCK_LOCX
@ RGN_TYPE_WINDOW
@ SPACE_NLA
@ SPACE_GRAPH
@ SPACE_VIEW3D
@ V3D_AROUND_CENTER_BOUNDS
@ V3D_AROUND_CURSOR
@ V3D_AROUND_LOCAL_ORIGINS
@ V3D_ORIENT_GLOBAL
@ V3D_ORIENT_VIEW
#define NUM_STR_REP_LEN
bool applyNumInput(NumInput *n, float *vec)
Definition numinput.cc:190
void outputNumInput(NumInput *n, char *str, const UnitSettings &unit_settings)
Definition numinput.cc:88
bool hasNumInput(const NumInput *n)
Definition numinput.cc:171
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:117
#define C
Definition RandGen.cpp:29
BMesh const char void * data
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
nullptr float
#define str(s)
ccl_device_inline float2 fabs(const float2 a)
TransConvertTypeInfo TransConvertType_Pose
TransConvertTypeInfo TransConvertType_Mesh
static void protectedAxisAngleBits(short protectflag, float axis[3], float *angle, const float oldAxis[3], float oldAngle)
TransConvertTypeInfo TransConvertType_Sculpt
bool transform_mode_is_changeable(const int mode)
void headerRotation(TransInfo *t, char *str, const int str_size, float final)
static void protectedRotateBits(short protectflag, float eul[3], const float oldeul[3])
bool transform_snap_increment(const TransInfo *t, float *r_val)
bool transform_mode_is_axis_pointing_to_screen(const TransInfo *t, const float3 &axis)
void protectedTransBits(short protectflag, float vec[3])
void protectedScaleBits(short protectflag, float scale[3])
void view_vector_calc(const TransInfo *t, const float focus[3], float r_vec[3])
static void constraintob_from_transdata(bConstraintOb *cob, TransDataExtension *td_ext)
void transform_convert_mesh_customdatacorrect_init(TransInfo *t)
void headerResize(TransInfo *t, const float vec[3], char *str, const int str_size)
void ElementRotation_ex(const TransInfo *t, const TransDataContainer *tc, TransData *td, TransDataExtension *td_ext, const float mat[3][3], const float *center)
static void protectedQuaternionBits(short protectflag, float quat[4], const float oldquat[4])
void transform_mode_default_modal_orientation_set(TransInfo *t, int type)
eTfmMode transform_mode_really_used(bContext *C, eTfmMode mode)
void transform_gizmo_3d_model_from_constraint_and_mode_set(TransInfo *t)
void constraintScaleLim(const TransInfo *t, const TransDataContainer *tc, int td_index)
bool transform_mode_affect_only_locations(const TransInfo *t)
static TransModeInfo * mode_info_get(TransInfo *t, const int mode)
void ElementRotation(const TransInfo *t, const TransDataContainer *tc, TransData *td, TransDataExtension *td_ext, const float mat[3][3], const short around)
void constraintTransLim(const TransInfo *t, const TransDataContainer *tc, TransData *td)
TransConvertTypeInfo TransConvertType_Object
bool transdata_check_local_center(const TransInfo *t, short around)
void transform_mode_init(TransInfo *t, wmOperator *op, const int mode)
short calc_orientation_from_type_ex(const Scene *scene, ViewLayer *view_layer, const View3D *v3d, const RegionView3D *rv3d, Object *ob, Object *obedit, short orientation_index, int pivot_point, float r_mat[3][3])
void ElementResize(const TransInfo *t, const TransDataContainer *tc, int td_index, const float mat[3][3])
void transform_mode_rotation_axis_get(const TransInfo *t, float3 &r_axis)
static void constraintRotLim(const TransInfo *, TransData *td, TransDataExtension *td_ext)
static void TransMat3ToSize(const float mat[3][3], const float smat[3][3], float size[3])
void transform_orientations_current_set(TransInfo *t, const short orient_index)
T interpolate(const T &a, const T &b, const FactorT &t)
T max(const T &a, const T &b)
VecBase< float, 3 > float3
#define fabsf
void * regiondata
short idx_max
struct RenderData r
struct UnitSettings unit
float matrix[4][4]
void(* evaluate_constraint)(struct bConstraint *con, struct bConstraintOb *cob, struct ListBase *targets)
struct bConstraint * next
void(* applyRot)(const TransInfo *t, const TransDataContainer *tc, const TransData *td, float r_axis[3])
Definition transform.hh:596
void(* applySize)(const TransInfo *t, const TransDataContainer *tc, const TransData *td, float r_smat[3][3])
Definition transform.hh:591
TransConvertTypeInfo * data_type
Definition transform.hh:810
struct blender::ed::transform::TransInfo::@342160341045112220003361360177273117120157367076 orient[3]
void(* init_fn)(TransInfo *, wmOperator *)
i
Definition text_draw.cc:230
#define T_PROP_EDIT_ALL
Definition transform.hh:28
conversion and adaptation of different datablocks to a common struct.
transform modes used by different operators.