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