Blender V4.3
transform_convert_armature.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
11
12#include "MEM_guardedalloc.h"
13
14#include "BLI_ghash.h"
15#include "BLI_listbase.h"
16#include "BLI_math_matrix.h"
17#include "BLI_math_rotation.h"
18#include "BLI_math_vector.h"
19
20#include "BKE_action.hh"
21#include "BKE_armature.hh"
22#include "BKE_constraint.h"
23#include "BKE_context.hh"
24#include "BKE_report.hh"
25
26#include "BIK_api.h"
27
28#include "ED_anim_api.hh"
29#include "ED_armature.hh"
30
31#include "DEG_depsgraph.hh"
33
34#include "ANIM_action.hh"
36#include "ANIM_keyframing.hh"
37#include "ANIM_rna.hh"
38
39#include "transform.hh"
41#include "transform_snap.hh"
42
43/* Own include. */
44#include "transform_convert.hh"
45
48 float tail[3];
49 float rad_head;
50 float rad_tail;
51 float roll;
52 float head[3];
53 float dist;
54 float xwidth;
55 float zwidth;
56};
57
58/* Return if we need to update motion paths, only if they already exist,
59 * and we will insert a keyframe at the end of transform. */
61{
64 }
65
66 return false;
67}
68
70 bKinematicConstraint *targetless_con)
71{
73 nullptr, pchan, "TempConstraint", CONSTRAINT_TYPE_KINEMATIC);
74
75 /* For draw, but also for detecting while pose solving. */
77
78 bKinematicConstraint *temp_con_data = static_cast<bKinematicConstraint *>(con->data);
79
80 if (targetless_con) {
81 /* If exists, use values from last targetless (but disabled) IK-constraint as base. */
82 *temp_con_data = *targetless_con;
83 }
84 else {
85 temp_con_data->flag = CONSTRAINT_IK_TIP;
86 }
87
89
90 return con;
91}
92
94{
96 /* TODO(sergey): Consider doing partial update only. */
98}
99
100/* -------------------------------------------------------------------- */
105{
106 bConstraint *con = static_cast<bConstraint *>(pchan->constraints.first);
107
108 for (; con; con = con->next) {
109 if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->flag & CONSTRAINT_OFF) == 0 &&
110 (con->enforce != 0.0f))
111 {
112 bKinematicConstraint *data = static_cast<bKinematicConstraint *>(con->data);
113
114 if (data->tar == nullptr) {
115 return data;
116 }
117 if (data->tar->type == OB_ARMATURE && data->subtarget[0] == 0) {
118 return data;
119 }
120 }
121 }
122 return nullptr;
123}
124
129{
130 bKinematicConstraint *targetless = nullptr;
132
133 /* Sanity check. */
134 if (pchan == nullptr) {
135 return 0;
136 }
137
138 /* Rule: not if there's already an IK on this channel. */
139 LISTBASE_FOREACH (bConstraint *, con, &pchan->constraints) {
140 if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->flag & CONSTRAINT_OFF) == 0) {
141 data = static_cast<bKinematicConstraint *>(con->data);
142
143 if (data->tar == nullptr || (data->tar->type == OB_ARMATURE && data->subtarget[0] == '\0')) {
144 /* Make reference to constraint to base things off later
145 * (if it's the last targetless constraint encountered). */
146 targetless = (bKinematicConstraint *)con->data;
147
148 /* But, if this is a targetless IK, we make it auto anyway (for the children loop). */
149 if (con->enforce != 0.0f) {
150 data->flag |= CONSTRAINT_IK_AUTO;
151
152 /* If no chain length has been specified,
153 * just make things obey standard rotation locks too. */
154 if (data->rootbone == 0) {
155 for (bPoseChannel *pchan_iter = pchan; pchan_iter; pchan_iter = pchan_iter->parent) {
156 /* Here, we set IK-settings for bone from `pchan->protectflag`. */
157 /* XXX: careful with quaternion/axis-angle rotations
158 * where we're locking 4d components. */
159 if (pchan_iter->protectflag & OB_LOCK_ROTX) {
160 pchan_iter->ikflag |= BONE_IK_NO_XDOF_TEMP;
161 }
162 if (pchan_iter->protectflag & OB_LOCK_ROTY) {
163 pchan_iter->ikflag |= BONE_IK_NO_YDOF_TEMP;
164 }
165 if (pchan_iter->protectflag & OB_LOCK_ROTZ) {
166 pchan_iter->ikflag |= BONE_IK_NO_ZDOF_TEMP;
167 }
168 }
169 }
170
171 /* Return early (as in: don't actually create a temporary constraint here), since adding
172 * will take place later in add_pose_transdata() for targetless constraints. */
173 return 0;
174 }
175 }
176
177 if ((con->flag & CONSTRAINT_DISABLE) == 0 && (con->enforce != 0.0f)) {
178 return 0;
179 }
180 }
181 }
182
183 data = static_cast<bKinematicConstraint *>(add_temporary_ik_constraint(pchan, targetless)->data);
184
185 copy_v3_v3(data->grabtarget, pchan->pose_tail);
186
187 /* Watch-it! has to be 0 here, since we're still on the
188 * same bone for the first time through the loop #25885. */
189 data->rootbone = 0;
190
191 /* We only include bones that are part of a continual connected chain. */
192 do {
193 /* Here, we set IK-settings for bone from `pchan->protectflag`. */
194 /* XXX: careful with quaternion/axis-angle rotations where we're locking 4D components. */
195 if (pchan->protectflag & OB_LOCK_ROTX) {
197 }
198 if (pchan->protectflag & OB_LOCK_ROTY) {
200 }
201 if (pchan->protectflag & OB_LOCK_ROTZ) {
203 }
204
205 /* Now we count this pchan as being included. */
206 data->rootbone++;
207
208 /* Continue to parent, but only if we're connected to it. */
209 if (pchan->bone->flag & BONE_CONNECTED) {
210 pchan = pchan->parent;
211 }
212 else {
213 pchan = nullptr;
214 }
215 } while (pchan);
216
217 /* Make a copy of maximum chain-length. */
218 data->max_rootbone = data->rootbone;
219
220 return 1;
221}
222
226static short pose_grab_with_ik_children(bPose *pose, Bone *bone)
227{
228 short wentdeeper = 0, added = 0;
229
230 /* Go deeper if children & children are connected. */
231 LISTBASE_FOREACH (Bone *, bonec, &bone->childbase) {
232 if (bonec->flag & BONE_CONNECTED) {
233 wentdeeper = 1;
234 added += pose_grab_with_ik_children(pose, bonec);
235 }
236 }
237 if (wentdeeper == 0) {
238 bPoseChannel *pchan = BKE_pose_channel_find_name(pose, bone->name);
239 if (pchan) {
240 added += pose_grab_with_ik_add(pchan);
241 }
242 }
243
244 return added;
245}
246
247/* Main call which adds temporal IK chains. */
248static short pose_grab_with_ik(Main *bmain, Object *ob)
249{
250 bArmature *arm;
251 Bone *bonec;
252 short tot_ik = 0;
253
254 if ((ob == nullptr) || (ob->pose == nullptr) || (ob->mode & OB_MODE_POSE) == 0) {
255 return 0;
256 }
257
258 arm = static_cast<bArmature *>(ob->data);
259
260 /* Rule: allow multiple Bones
261 * (but they must be selected, and only one ik-solver per chain should get added). */
262 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
263 if (BKE_pose_is_bonecoll_visible(arm, pchan)) {
264 if (pchan->bone->flag & (BONE_SELECTED | BONE_TRANSFORM_MIRROR)) {
265 /* Rule: no IK for solitary (unconnected) bones. */
266 for (bonec = static_cast<Bone *>(pchan->bone->childbase.first); bonec; bonec = bonec->next)
267 {
268 if (bonec->flag & BONE_CONNECTED) {
269 break;
270 }
271 }
272 if ((pchan->bone->flag & BONE_CONNECTED) == 0 && (bonec == nullptr)) {
273 continue;
274 }
275
276 /* Rule: if selected Bone is not a root bone, it gets a temporal IK. */
277 if (pchan->parent) {
278 /* Only adds if there's no IK yet (and no parent bone was selected). */
279 bPoseChannel *parent;
280 for (parent = pchan->parent; parent; parent = parent->parent) {
281 if (parent->bone->flag & (BONE_SELECTED | BONE_TRANSFORM_MIRROR)) {
282 break;
283 }
284 }
285 if (parent == nullptr) {
286 tot_ik += pose_grab_with_ik_add(pchan);
287 }
288 }
289 else {
290 /* Rule: go over the children and add IK to the tips. */
291 tot_ik += pose_grab_with_ik_children(ob->pose, pchan->bone);
292 }
293 }
294 }
295 }
296
297 /* `ITaSC` needs clear for new IK constraints. */
298 if (tot_ik) {
300 }
301
302 return (tot_ik) ? 1 : 0;
303}
304
307/* -------------------------------------------------------------------- */
315 struct {
316 float loc[3];
317 float size[3];
318 union {
319 float eul[3];
320 float quat[4];
321 float axis_angle[4];
322 };
325 float roll1;
326 float roll2;
332 float offset_mtx[4][4];
333};
334
336 bPoseChannel *pchan,
337 bPoseChannel *pchan_orig,
338 bool is_mirror_relative)
339{
340 pid->pchan = pchan;
341 copy_v3_v3(pid->orig.loc, pchan->loc);
342 copy_v3_v3(pid->orig.size, pchan->size);
343 pid->orig.curve_in_x = pchan->curve_in_x;
344 pid->orig.curve_out_x = pchan->curve_out_x;
345 pid->orig.roll1 = pchan->roll1;
346 pid->orig.roll2 = pchan->roll2;
347
348 if (pchan->rotmode > 0) {
349 copy_v3_v3(pid->orig.eul, pchan->eul);
350 }
351 else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
352 copy_v3_v3(pid->orig.axis_angle, pchan->rotAxis);
353 pid->orig.axis_angle[3] = pchan->rotAngle;
354 }
355 else {
356 copy_qt_qt(pid->orig.quat, pchan->quat);
357 }
358
359 if (is_mirror_relative) {
360 float pchan_mtx[4][4];
361 float pchan_mtx_mirror[4][4];
362
363 float flip_mtx[4][4];
364 unit_m4(flip_mtx);
365 flip_mtx[0][0] = -1;
366
367 BKE_pchan_to_mat4(pchan_orig, pchan_mtx_mirror);
368 BKE_pchan_to_mat4(pchan, pchan_mtx);
369
370 mul_m4_m4m4(pchan_mtx_mirror, pchan_mtx_mirror, flip_mtx);
371 mul_m4_m4m4(pchan_mtx_mirror, flip_mtx, pchan_mtx_mirror);
372
373 invert_m4(pchan_mtx_mirror);
374 mul_m4_m4m4(pid->offset_mtx, pchan_mtx, pchan_mtx_mirror);
375 }
376 else {
377 unit_m4(pid->offset_mtx);
378 }
379}
380
383/* -------------------------------------------------------------------- */
388{
389 Bone *bone = pchan->bone;
390 float pmat[3][3], omat[3][3];
391 float cmat[3][3], tmat[3][3];
392 float vec[3];
393
394 copy_v3_v3(vec, pchan->pose_mat[3]);
395 copy_v3_v3(td->center, vec);
396
397 td->ob = ob;
398 td->flag = TD_SELECTED;
399 if (bone->flag & BONE_HINGE_CHILD_TRANSFORM) {
400 td->flag |= TD_NOCENTER;
401 }
402
403 if (bone->flag & BONE_TRANSFORM_CHILD) {
404 td->flag |= TD_NOCENTER;
405 td->flag |= TD_NO_LOC;
406 }
407
408 td->extra = pchan;
409 td->protectflag = pchan->protectflag;
410
411 td->loc = pchan->loc;
412 copy_v3_v3(td->iloc, pchan->loc);
413
414 td->ext->size = pchan->size;
415 copy_v3_v3(td->ext->isize, pchan->size);
416
417 if (pchan->rotmode > 0) {
418 td->ext->rot = pchan->eul;
419 td->ext->rotAxis = nullptr;
420 td->ext->rotAngle = nullptr;
421 td->ext->quat = nullptr;
422
423 copy_v3_v3(td->ext->irot, pchan->eul);
424 }
425 else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
426 td->ext->rot = nullptr;
427 td->ext->rotAxis = pchan->rotAxis;
428 td->ext->rotAngle = &pchan->rotAngle;
429 td->ext->quat = nullptr;
430
431 td->ext->irotAngle = pchan->rotAngle;
432 copy_v3_v3(td->ext->irotAxis, pchan->rotAxis);
433 }
434 else {
435 td->ext->rot = nullptr;
436 td->ext->rotAxis = nullptr;
437 td->ext->rotAngle = nullptr;
438 td->ext->quat = pchan->quat;
439
440 copy_qt_qt(td->ext->iquat, pchan->quat);
441 }
442 td->ext->rotOrder = pchan->rotmode;
443
444 /* Proper way to get parent transform + our own transform + constraints transform. */
445 copy_m3_m4(omat, ob->object_to_world().ptr());
446
447 /* New code, using "generic" BKE_bone_parent_transform_calc_from_pchan(). */
448 {
450 float rpmat[3][3];
451
453 if (t->mode == TFM_TRANSLATION) {
454 copy_m3_m4(pmat, bpt.loc_mat);
455 }
456 else {
457 copy_m3_m4(pmat, bpt.rotscale_mat);
458 }
459
460 /* Grrr! Exceptional case: When translating pose bones that are either Hinge or NoLocal,
461 * and want align snapping, we just need both loc_mat and rotscale_mat.
462 * So simply always store rotscale mat in td->ext, and always use it to apply rotations...
463 * Ugly to need such hacks! :/ */
464 copy_m3_m4(rpmat, bpt.rotscale_mat);
465
466 if (constraints_list_needinv(t, &pchan->constraints)) {
467 copy_m3_m4(tmat, pchan->constinv);
468 invert_m3_m3(cmat, tmat);
469 mul_m3_series(td->mtx, cmat, omat, pmat);
470 mul_m3_series(td->ext->r_mtx, cmat, omat, rpmat);
471 }
472 else {
473 mul_m3_series(td->mtx, omat, pmat);
474 mul_m3_series(td->ext->r_mtx, omat, rpmat);
475 }
476 invert_m3_m3(td->ext->r_smtx, td->ext->r_mtx);
477 }
478
480
481 /* Exceptional case: rotate the pose bone which also applies transformation
482 * when a parentless bone has #BONE_NO_LOCAL_LOCATION []. */
484 {
485 if (pchan->parent) {
486 /* Same as `td->smtx` but without `pchan->bone->bone_mat`. */
487 td->flag |= TD_PBONE_LOCAL_MTX_C;
488 mul_m3_m3m3(td->ext->l_smtx, pchan->bone->bone_mat, td->smtx);
489 }
490 else {
491 td->flag |= TD_PBONE_LOCAL_MTX_P;
492 }
493 }
494
495 /* For `axismtx` we use the bone's own transform. */
496 copy_m3_m4(pmat, pchan->pose_mat);
497 mul_m3_m3m3(td->axismtx, omat, pmat);
499
500 if (t->orient_type_mask & (1 << V3D_ORIENT_GIMBAL)) {
501 if (!gimbal_axis_pose(ob, pchan, td->ext->axismtx_gimbal)) {
503 }
504 }
505
506 if (t->mode == TFM_BONE_ENVELOPE_DIST) {
507 td->loc = nullptr;
508 td->val = &bone->dist;
509 td->ival = bone->dist;
510 }
511 else if (t->mode == TFM_BONESIZE) {
512 /* Abusive storage of scale in the loc pointer :). */
513 td->loc = &bone->xwidth;
514 copy_v3_v3(td->iloc, td->loc);
515 td->val = nullptr;
516 }
517
518 /* In this case we can do target-less IK grabbing. */
519 if (t->mode == TFM_TRANSLATION) {
521 if (data) {
522 if (data->flag & CONSTRAINT_IK_TIP) {
523 copy_v3_v3(data->grabtarget, pchan->pose_tail);
524 }
525 else {
526 copy_v3_v3(data->grabtarget, pchan->pose_head);
527 }
528 td->loc = data->grabtarget;
529 copy_v3_v3(td->iloc, td->loc);
530
531 data->flag |= CONSTRAINT_IK_AUTO;
532
533 /* Add a temporary auto IK constraint here, as we will only temporarily active this
534 * targetless bone during transform. (Targetless IK constraints are treated as if they are
535 * disabled unless they are transformed).
536 * Only do this for targetless IK though, AutoIK already added a constraint in
537 * pose_grab_with_ik_add() beforehand. */
538 if ((data->flag & CONSTRAINT_IK_TEMP) == 0) {
539 add_temporary_ik_constraint(pchan, data);
540 Main *bmain = CTX_data_main(t->context);
542 }
543
544 /* Only object matrix correction. */
545 copy_m3_m3(td->mtx, omat);
547 }
548 }
549
550 /* Store reference to first constraint. */
551 td->con = static_cast<bConstraint *>(pchan->constraints.first);
552}
553
554static void createTransPose(bContext * /*C*/, TransInfo *t)
555{
556 Main *bmain = CTX_data_main(t->context);
557
558 t->data_len_all = 0;
559
560 bool has_translate_rotate_buf[2] = {false, false};
561 bool *has_translate_rotate = (t->mode == TFM_TRANSLATION) ? has_translate_rotate_buf : nullptr;
562
564 Object *ob = tc->poseobj;
565 bPose *pose = ob->pose;
566
567 bArmature *arm;
568
569 /* Check validity of state. */
570 arm = BKE_armature_from_object(tc->poseobj);
571 if ((arm == nullptr) || (pose == nullptr)) {
572 continue;
573 }
574
575 const bool mirror = ((pose->flag & POSE_MIRROR_EDIT) != 0);
576
577 /* Set flags. */
579
580 /* Now count, and check if we have autoIK or have to switch from translate to rotate. */
581 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
582 Bone *bone = pchan->bone;
583 if (!(bone->flag & BONE_TRANSFORM)) {
584 continue;
585 }
586
587 tc->data_len++;
588
589 if (has_translate_rotate != nullptr) {
590 if (has_translate_rotate[0] && has_translate_rotate[1]) {
591 continue;
592 }
593
594 if (has_targetless_ik(pchan) == nullptr) {
595 if (pchan->parent && (bone->flag & BONE_CONNECTED)) {
596 if (bone->flag & BONE_HINGE_CHILD_TRANSFORM) {
597 has_translate_rotate[0] = true;
598 }
599 }
600 else {
601 if ((pchan->protectflag & OB_LOCK_LOC) != OB_LOCK_LOC) {
602 has_translate_rotate[0] = true;
603 }
604 }
605 if ((pchan->protectflag & OB_LOCK_ROT) != OB_LOCK_ROT) {
606 has_translate_rotate[1] = true;
607 }
608 }
609 else {
610 has_translate_rotate[0] = true;
611 }
612 }
613 }
614
615 if (tc->data_len == 0) {
616 continue;
617 }
618
619 if (arm->flag & ARM_RESTPOS) {
620 if (ELEM(t->mode, TFM_DUMMY, TFM_BONESIZE) == 0) {
621 BKE_report(t->reports, RPT_ERROR, "Cannot change Pose when 'Rest Position' is enabled");
622 tc->data_len = 0;
623 continue;
624 }
625 }
626
627 if (mirror) {
628 int total_mirrored = 0;
629 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
630 /* Clear the MIRROR flag from previous runs. */
631 pchan->bone->flag &= ~BONE_TRANSFORM_MIRROR;
632
633 if ((pchan->bone->flag & BONE_TRANSFORM) &&
634 BKE_pose_channel_get_mirrored(ob->pose, pchan->name))
635 {
636 total_mirrored++;
637 }
638 }
639
640 PoseInitData_Mirror *pid = static_cast<PoseInitData_Mirror *>(
641 MEM_mallocN((total_mirrored + 1) * sizeof(PoseInitData_Mirror), "PoseInitData_Mirror"));
642
643 /* Trick to terminate iteration. */
644 pid[total_mirrored].pchan = nullptr;
645
646 tc->custom.type.data = pid;
647 tc->custom.type.use_free = true;
648 }
649 }
650
652 if (tc->data_len == 0) {
653 continue;
654 }
655 Object *ob = tc->poseobj;
656 TransData *td;
658 int i;
659
660 PoseInitData_Mirror *pid = static_cast<PoseInitData_Mirror *>(tc->custom.type.data);
661 int pid_index = 0;
662 bPose *pose = ob->pose;
663
664 if (pose == nullptr) {
665 continue;
666 }
667
668 const bool mirror = ((pose->flag & POSE_MIRROR_EDIT) != 0);
669 const bool is_mirror_relative = ((pose->flag & POSE_MIRROR_RELATIVE) != 0);
670
671 /* We also allow non-active objects to be transformed, in weight-paint. */
672 tc->poseobj = ob;
673
674 /* Initialize trans data. */
675 td = tc->data = static_cast<TransData *>(
676 MEM_callocN(tc->data_len * sizeof(TransData), "TransPoseBone"));
677 tdx = tc->data_ext = static_cast<TransDataExtension *>(
678 MEM_callocN(tc->data_len * sizeof(TransDataExtension), "TransPoseBoneExt"));
679 for (i = 0; i < tc->data_len; i++, td++, tdx++) {
680 td->ext = tdx;
681 td->val = nullptr;
682 }
683
684 if (mirror) {
685 LISTBASE_FOREACH (bPoseChannel *, pchan, &pose->chanbase) {
686 if (pchan->bone->flag & BONE_TRANSFORM) {
687 bPoseChannel *pchan_mirror = BKE_pose_channel_get_mirrored(ob->pose, pchan->name);
688 if (pchan_mirror) {
689 pchan_mirror->bone->flag |= BONE_TRANSFORM_MIRROR;
690 pose_mirror_info_init(&pid[pid_index], pchan_mirror, pchan, is_mirror_relative);
691 pid_index++;
692 }
693 }
694 }
695 }
696
697 /* Do we need to add temporal IK chains? */
698 if ((pose->flag & POSE_AUTO_IK) && t->mode == TFM_TRANSLATION) {
699 if (pose_grab_with_ik(bmain, ob)) {
700 t->flag |= T_AUTOIK;
701 has_translate_rotate[0] = true;
702 }
703 }
704
705 /* Use pose channels to fill trans data. */
706 td = tc->data;
707 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
708 if (pchan->bone->flag & BONE_TRANSFORM) {
709 add_pose_transdata(t, pchan, ob, td);
710 td++;
711 }
712 }
713
714 if (td != (tc->data + tc->data_len)) {
715 BKE_report(t->reports, RPT_DEBUG, "Bone selection count error");
716 }
717 }
718
719 /* Initialize initial auto=IK chain-length's? */
720 if (t->flag & T_AUTOIK) {
722 }
723
724 /* If there are no translatable bones, do rotation. */
725 if ((t->mode == TFM_TRANSLATION) && !has_translate_rotate[0]) {
726 if (has_translate_rotate[1]) {
727 t->mode = TFM_ROTATION;
728 }
729 else {
730 t->mode = TFM_RESIZE;
731 }
732 }
733}
734
736{
737 t->data_len_all = 0;
738
740 bArmature *arm = static_cast<bArmature *>(tc->obedit->data);
741 ListBase *edbo = arm->edbo;
742 bool mirror = ((arm->flag & ARM_MIRROR_EDIT) != 0);
743 int total_mirrored = 0;
744
745 tc->data_len = 0;
746 LISTBASE_FOREACH (EditBone *, ebo, edbo) {
747 const int data_len_prev = tc->data_len;
748
749 if (EBONE_VISIBLE(arm, ebo) && !(ebo->flag & BONE_EDITMODE_LOCKED)) {
751 if (ebo->flag & BONE_SELECTED) {
752 tc->data_len++;
753 }
754 }
755 else if (t->mode == TFM_BONE_ROLL) {
756 if (ebo->flag & BONE_SELECTED) {
757 tc->data_len++;
758 }
759 }
760 else {
761 if (ebo->flag & BONE_TIPSEL) {
762 tc->data_len++;
763 }
764 if (ebo->flag & BONE_ROOTSEL) {
765 tc->data_len++;
766 }
767 }
768 }
769
770 if (mirror && (data_len_prev < tc->data_len)) {
771 EditBone *eboflip = ED_armature_ebone_get_mirrored(arm->edbo, ebo);
772 if (eboflip) {
773 total_mirrored++;
774 }
775 }
776 }
777 if (!tc->data_len) {
778 continue;
779 }
780
781 if (mirror) {
782 BoneInitData *bid = static_cast<BoneInitData *>(
783 MEM_mallocN((total_mirrored + 1) * sizeof(BoneInitData), "BoneInitData"));
784
785 /* Trick to terminate iteration. */
786 bid[total_mirrored].bone = nullptr;
787
788 tc->custom.type.data = bid;
789 tc->custom.type.use_free = true;
790 }
791 t->data_len_all += tc->data_len;
792 }
793
795 t->data_len_all = -1;
796
798 if (!tc->data_len) {
799 continue;
800 }
801
802 bArmature *arm = static_cast<bArmature *>(tc->obedit->data);
803 ListBase *edbo = arm->edbo;
804 TransData *td, *td_old;
805 float mtx[3][3], smtx[3][3], bonemat[3][3];
806 bool mirror = ((arm->flag & ARM_MIRROR_EDIT) != 0);
807 BoneInitData *bid = static_cast<BoneInitData *>(tc->custom.type.data);
808
809 copy_m3_m4(mtx, tc->obedit->object_to_world().ptr());
811
812 td = tc->data = static_cast<TransData *>(
813 MEM_callocN(tc->data_len * sizeof(TransData), "TransEditBone"));
814 int i = 0;
815
816 LISTBASE_FOREACH (EditBone *, ebo, edbo) {
817 td_old = td;
818
819 /* (length == 0.0) on extrude, used for scaling radius of bone points. */
820 ebo->oldlength = ebo->length;
821
822 if (EBONE_VISIBLE(arm, ebo) && !(ebo->flag & BONE_EDITMODE_LOCKED)) {
823 if (t->mode == TFM_BONE_ENVELOPE) {
824 if (ebo->flag & BONE_ROOTSEL) {
825 td->val = &ebo->rad_head;
826 td->ival = *td->val;
827
828 copy_v3_v3(td->center, ebo->head);
829 td->flag = TD_SELECTED;
830
831 copy_m3_m3(td->smtx, smtx);
832 copy_m3_m3(td->mtx, mtx);
833
834 td->loc = nullptr;
835 td->ext = nullptr;
836 td->ob = tc->obedit;
837
838 td++;
839 }
840 if (ebo->flag & BONE_TIPSEL) {
841 td->val = &ebo->rad_tail;
842 td->ival = *td->val;
843 copy_v3_v3(td->center, ebo->tail);
844 td->flag = TD_SELECTED;
845
846 copy_m3_m3(td->smtx, smtx);
847 copy_m3_m3(td->mtx, mtx);
848
849 td->loc = nullptr;
850 td->ext = nullptr;
851 td->ob = tc->obedit;
852
853 td++;
854 }
855 }
857 if (ebo->flag & BONE_SELECTED) {
858 if (t->mode == TFM_BONE_ENVELOPE_DIST) {
859 td->loc = nullptr;
860 td->val = &ebo->dist;
861 td->ival = ebo->dist;
862 }
863 else {
864 /* Abusive storage of scale in the loc pointer :). */
865 td->loc = &ebo->xwidth;
866 copy_v3_v3(td->iloc, td->loc);
867 td->val = nullptr;
868 }
869 copy_v3_v3(td->center, ebo->head);
870 td->flag = TD_SELECTED;
871
872 /* Use local bone matrix. */
873 ED_armature_ebone_to_mat3(ebo, bonemat);
874 mul_m3_m3m3(td->mtx, mtx, bonemat);
875 invert_m3_m3(td->smtx, td->mtx);
876
877 copy_m3_m3(td->axismtx, td->mtx);
879
880 td->ext = nullptr;
881 td->ob = tc->obedit;
882
883 td++;
884 }
885 }
886 else if (t->mode == TFM_BONE_ROLL) {
887 if (ebo->flag & BONE_SELECTED) {
888 td->loc = nullptr;
889 td->val = &(ebo->roll);
890 td->ival = ebo->roll;
891
892 copy_v3_v3(td->center, ebo->head);
893 td->flag = TD_SELECTED;
894
895 td->ext = nullptr;
896 td->ob = tc->obedit;
897
898 td++;
899 }
900 }
901 else {
902 if (ebo->flag & BONE_TIPSEL) {
903 copy_v3_v3(td->iloc, ebo->tail);
904
905 /* Don't allow single selected tips to have a modified center,
906 * causes problem with snapping (see #45974).
907 * However, in rotation mode, we want to keep that 'rotate bone around root with
908 * only its tip selected' behavior (see #46325). */
909 if ((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
910 ((t->mode == TFM_ROTATION) || (ebo->flag & BONE_ROOTSEL)))
911 {
912 copy_v3_v3(td->center, ebo->head);
913 }
914 else {
915 copy_v3_v3(td->center, td->iloc);
916 }
917
918 td->loc = ebo->tail;
919 td->flag = TD_SELECTED;
920 if (ebo->flag & BONE_EDITMODE_LOCKED) {
922 }
923
924 copy_m3_m3(td->smtx, smtx);
925 copy_m3_m3(td->mtx, mtx);
926
928
929 if ((ebo->flag & BONE_ROOTSEL) == 0) {
930 td->extra = ebo;
931 td->ival = ebo->roll;
932 }
933
934 td->ext = nullptr;
935 td->val = nullptr;
936 td->ob = tc->obedit;
937
938 td++;
939 }
940 if (ebo->flag & BONE_ROOTSEL) {
941 copy_v3_v3(td->iloc, ebo->head);
942 copy_v3_v3(td->center, td->iloc);
943 td->loc = ebo->head;
944 td->flag = TD_SELECTED;
945 if (ebo->flag & BONE_EDITMODE_LOCKED) {
947 }
948
949 copy_m3_m3(td->smtx, smtx);
950 copy_m3_m3(td->mtx, mtx);
951
953
954 td->extra = ebo; /* To fix roll. */
955 td->ival = ebo->roll;
956
957 td->ext = nullptr;
958 td->val = nullptr;
959 td->ob = tc->obedit;
960
961 td++;
962 }
963 }
964 }
965
966 if (mirror && (td_old != td)) {
967 EditBone *eboflip = ED_armature_ebone_get_mirrored(arm->edbo, ebo);
968 if (eboflip) {
969 bid[i].bone = eboflip;
970 bid[i].dist = eboflip->dist;
971 bid[i].rad_head = eboflip->rad_head;
972 bid[i].rad_tail = eboflip->rad_tail;
973 bid[i].roll = eboflip->roll;
974 bid[i].xwidth = eboflip->xwidth;
975 bid[i].zwidth = eboflip->zwidth;
976 copy_v3_v3(bid[i].head, eboflip->head);
977 copy_v3_v3(bid[i].tail, eboflip->tail);
978 i++;
979 }
980 }
981 }
982
983 if (mirror) {
984 /* Trick to terminate iteration. */
985 BLI_assert(i + 1 == (MEM_allocN_len(bid) / sizeof(*bid)));
986 bid[i].bone = nullptr;
987 }
988 }
989}
990
993/* -------------------------------------------------------------------- */
998{
999 bArmature *arm;
1000 BoneInitData *bid = static_cast<BoneInitData *>(tc->custom.type.data);
1001 EditBone *ebo;
1002
1003 if (tc->obedit) {
1004 arm = static_cast<bArmature *>(tc->obedit->data);
1005 }
1006 else {
1007 BLI_assert(tc->poseobj != nullptr);
1008 arm = static_cast<bArmature *>(tc->poseobj->data);
1009 }
1010
1011 while (bid->bone) {
1012 ebo = bid->bone;
1013
1014 ebo->dist = bid->dist;
1015 ebo->rad_head = bid->rad_head;
1016 ebo->rad_tail = bid->rad_tail;
1017 ebo->roll = bid->roll;
1018 ebo->xwidth = bid->xwidth;
1019 ebo->zwidth = bid->zwidth;
1020 copy_v3_v3(ebo->head, bid->head);
1021 copy_v3_v3(ebo->tail, bid->tail);
1022
1023 if (arm->flag & ARM_MIRROR_EDIT) {
1024 /* Also move connected ebo_child, in case ebo_child's name aren't mirrored properly. */
1025 LISTBASE_FOREACH (EditBone *, ebo_child, arm->edbo) {
1026 if ((ebo_child->flag & BONE_CONNECTED) && (ebo_child->parent == ebo)) {
1027 copy_v3_v3(ebo_child->head, ebo->tail);
1028 ebo_child->rad_head = ebo->rad_tail;
1029 }
1030 }
1031
1032 /* Also move connected parent, in case parent's name isn't mirrored properly. */
1033 if ((ebo->flag & BONE_CONNECTED) && ebo->parent) {
1034 EditBone *parent = ebo->parent;
1035 copy_v3_v3(parent->tail, ebo->head);
1036 parent->rad_tail = ebo->rad_head;
1037 }
1038 }
1039
1040 bid++;
1041 }
1042}
1043
1045{
1046 if (t->state != TRANS_CANCEL) {
1048 }
1049
1051 bArmature *arm = static_cast<bArmature *>(tc->obedit->data);
1052 ListBase *edbo = arm->edbo;
1053 EditBone *ebo, *ebo_parent;
1054 TransData *td = tc->data;
1055 int i;
1056
1057 /* Ensure all bones are correctly adjusted. */
1058 LISTBASE_FOREACH (EditBone *, ebo, edbo) {
1059 ebo_parent = (ebo->flag & BONE_CONNECTED) ? ebo->parent : nullptr;
1060
1061 if (ebo_parent) {
1062 /* If this bone has a parent tip that has been moved. */
1063 if (ebo_parent->flag & BONE_TIPSEL) {
1064 copy_v3_v3(ebo->head, ebo_parent->tail);
1065 if (t->mode == TFM_BONE_ENVELOPE) {
1066 ebo->rad_head = ebo_parent->rad_tail;
1067 }
1068 }
1069 /* If this bone has a parent tip that has NOT been moved. */
1070 else {
1071 copy_v3_v3(ebo_parent->tail, ebo->head);
1072 if (t->mode == TFM_BONE_ENVELOPE) {
1073 ebo_parent->rad_tail = ebo->rad_head;
1074 }
1075 }
1076 }
1077
1078 /* On extrude bones, oldlength==0.0f, so we scale radius of points. */
1079 ebo->length = len_v3v3(ebo->head, ebo->tail);
1080 if (ebo->oldlength == 0.0f) {
1081 ebo->rad_head = 0.25f * ebo->length;
1082 ebo->rad_tail = 0.10f * ebo->length;
1083 ebo->dist = 0.25f * ebo->length;
1084 if (ebo->parent) {
1085 if (ebo->rad_head > ebo->parent->rad_tail) {
1086 ebo->rad_head = ebo->parent->rad_tail;
1087 }
1088 }
1089 }
1090 else if (t->mode != TFM_BONE_ENVELOPE) {
1091 /* If bones change length, lets do that for the deform distance as well. */
1092 ebo->dist *= ebo->length / ebo->oldlength;
1093 ebo->rad_head *= ebo->length / ebo->oldlength;
1094 ebo->rad_tail *= ebo->length / ebo->oldlength;
1095 ebo->oldlength = ebo->length;
1096
1097 if (ebo_parent) {
1098 ebo_parent->rad_tail = ebo->rad_head;
1099 }
1100 }
1101 }
1102
1104 /* Fix roll. */
1105 for (i = 0; i < tc->data_len; i++, td++) {
1106 if (td->extra) {
1107 float vec[3], up_axis[3];
1108 float qrot[4];
1109 float roll;
1110
1111 ebo = static_cast<EditBone *>(td->extra);
1112
1113 if (t->state == TRANS_CANCEL) {
1114 /* Restore roll. */
1115 ebo->roll = td->ival;
1116 }
1117 else {
1118 copy_v3_v3(up_axis, td->axismtx[2]);
1119
1120 sub_v3_v3v3(vec, ebo->tail, ebo->head);
1121 normalize_v3(vec);
1122 rotation_between_vecs_to_quat(qrot, td->axismtx[1], vec);
1123 mul_qt_v3(qrot, up_axis);
1124
1125 /* Roll has a tendency to flip in certain orientations - #34283, #33974. */
1126 roll = ED_armature_ebone_roll_to_vector(ebo, up_axis, false);
1127 ebo->roll = angle_compat_rad(roll, td->ival);
1128 }
1129 }
1130 }
1131 }
1132
1133 if (arm->flag & ARM_MIRROR_EDIT) {
1134 if (t->state != TRANS_CANCEL) {
1136 }
1137 else {
1138 restoreBones(tc);
1139 }
1140 }
1141 }
1142}
1143
1146/* -------------------------------------------------------------------- */
1155{
1156 float flip_mtx[4][4];
1157 unit_m4(flip_mtx);
1158 flip_mtx[0][0] = -1;
1159
1160 LISTBASE_FOREACH (bPoseChannel *, pchan_orig, &ob->pose->chanbase) {
1161 /* Clear the MIRROR flag from previous runs. */
1162 pchan_orig->bone->flag &= ~BONE_TRANSFORM_MIRROR;
1163 }
1164
1165 bPose *pose = ob->pose;
1166 PoseInitData_Mirror *pid = nullptr;
1167 if ((t->mode != TFM_BONESIZE) && (pose->flag & POSE_MIRROR_RELATIVE)) {
1168 pid = static_cast<PoseInitData_Mirror *>(tc->custom.type.data);
1169 }
1170
1171 TransData *td = tc->data;
1172 for (int i = tc->data_len; i--; td++) {
1173 bPoseChannel *pchan_orig = static_cast<bPoseChannel *>(td->extra);
1174 BLI_assert(pchan_orig->bone->flag & BONE_TRANSFORM);
1175 /* No layer check, correct mirror is more important. */
1176 bPoseChannel *pchan = BKE_pose_channel_get_mirrored(pose, pchan_orig->name);
1177 if (pchan == nullptr) {
1178 continue;
1179 }
1180
1181 /* Also do bbone scaling. */
1182 pchan->bone->xwidth = pchan_orig->bone->xwidth;
1183 pchan->bone->zwidth = pchan_orig->bone->zwidth;
1184
1185 /* We assume X-axis flipping for now. */
1186 pchan->curve_in_x = pchan_orig->curve_in_x * -1;
1187 pchan->curve_out_x = pchan_orig->curve_out_x * -1;
1188 pchan->roll1 = pchan_orig->roll1 * -1; /* XXX? */
1189 pchan->roll2 = pchan_orig->roll2 * -1; /* XXX? */
1190
1191 float pchan_mtx_final[4][4];
1192 BKE_pchan_to_mat4(pchan_orig, pchan_mtx_final);
1193 mul_m4_m4m4(pchan_mtx_final, pchan_mtx_final, flip_mtx);
1194 mul_m4_m4m4(pchan_mtx_final, flip_mtx, pchan_mtx_final);
1195 if (pid) {
1196 mul_m4_m4m4(pchan_mtx_final, pid->offset_mtx, pchan_mtx_final);
1197 }
1198 BKE_pchan_apply_mat4(pchan, pchan_mtx_final, false);
1199
1200 /* Set flag to let auto key-frame know to key-frame the mirrored bone. */
1201 pchan->bone->flag |= BONE_TRANSFORM_MIRROR;
1202
1203 /* In this case we can do target-less IK grabbing. */
1204 if (t->mode == TFM_TRANSLATION) {
1206 if (data == nullptr) {
1207 continue;
1208 }
1209 mul_v3_m4v3(data->grabtarget, flip_mtx, td->loc);
1210 if (pid) {
1211 /* TODO(@germano): Relative Mirror support. */
1212 }
1213 data->flag |= CONSTRAINT_IK_AUTO;
1214 /* Add a temporary auto IK constraint here, as we will only temporarily active this
1215 * target-less bone during transform. (Target-less IK constraints are treated as if they are
1216 * disabled unless they are transformed).
1217 * Only do this for targetless IK though, AutoIK already added a constraint in
1218 * pose_grab_with_ik_add() beforehand. */
1219 if ((data->flag & CONSTRAINT_IK_TEMP) == 0) {
1220 add_temporary_ik_constraint(pchan, data);
1221 Main *bmain = CTX_data_main(t->context);
1223 }
1224 }
1225
1226 if (pid) {
1227 pid++;
1228 }
1229 }
1230}
1231
1233{
1234 bPoseChannel *pchan = pid->pchan;
1235 copy_v3_v3(pchan->loc, pid->orig.loc);
1236 copy_v3_v3(pchan->size, pid->orig.size);
1237 pchan->curve_in_x = pid->orig.curve_in_x;
1238 pchan->curve_out_x = pid->orig.curve_out_x;
1239 pchan->roll1 = pid->orig.roll1;
1240 pchan->roll2 = pid->orig.roll2;
1241
1242 if (pchan->rotmode > 0) {
1243 copy_v3_v3(pchan->eul, pid->orig.eul);
1244 }
1245 else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
1246 copy_v3_v3(pchan->rotAxis, pid->orig.axis_angle);
1247 pchan->rotAngle = pid->orig.axis_angle[3];
1248 }
1249 else {
1250 copy_qt_qt(pchan->quat, pid->orig.quat);
1251 }
1252}
1253
1255{
1256 bPose *pose = tc->poseobj->pose;
1257
1258 if (!(pose->flag & POSE_MIRROR_EDIT)) {
1259 return;
1260 }
1261
1262 for (PoseInitData_Mirror *pid = static_cast<PoseInitData_Mirror *>(tc->custom.type.data);
1263 pid->pchan;
1264 pid++)
1265 {
1267 }
1268}
1269
1270/* Given the transform mode `tmode` return a Vector of RNA paths that were possibly modified during
1271 * that transformation. */
1273 const eTfmMode tmode,
1274 ToolSettings *toolsettings,
1275 const blender::StringRef rotation_path,
1276 const bool targetless_ik,
1277 const bool is_connected,
1278 const bool transforming_more_than_one_bone)
1279{
1280 blender::Vector<RNAPath> rna_paths;
1281
1282 /* Handle the cases where we always need to key location, regardless of
1283 * transform mode. */
1284 if (transforming_more_than_one_bone &&
1286 {
1287 rna_paths.append({"location"});
1288 }
1289 else if (toolsettings->transform_pivot_point == V3D_AROUND_CURSOR) {
1290 rna_paths.append({"location"});
1291 }
1292
1293 /* Handle the transform-mode-specific cases. */
1294 switch (tmode) {
1295 case TFM_TRANSLATION:
1296 /* NOTE: this used to *not* add location if we were doing targetless IK.
1297 * However, that was wrong because of the following situations:
1298 *
1299 * 1. The user can grab the *base* of the bone chain, in which case that
1300 * bone's location does indeed get its location moved, and thus needs
1301 * its location keyed.
1302 * 2. The user can also have bones outside of a bone chain selected, in
1303 * which case they get moved normally, and thus those
1304 * outside-of-a-chain bones need their location keyed.
1305 *
1306 * So for now we're just adding location regardless of targetless IK. This
1307 * unfortunately means that location gets keyed on a lot of bones that
1308 * don't need it when doing targetless ik, but that's better than
1309 * *failing* to key bones that *do* need it. Additionally, case 2 above
1310 * means that outside-of-a-chain bones also get their *rotation*
1311 * unnecessarily keyed when doing targetless IK on another selected chain.
1312 *
1313 * Being precise and only adding location/rotation for the bones that
1314 * really need it when doing targetless IK will require more information
1315 * to be passed to this function.
1316 *
1317 * TODO: get the needed information and make this more precise. */
1318 if (!is_connected) {
1319 rna_paths.append_non_duplicates({"location"});
1320 }
1321 if (targetless_ik) {
1322 rna_paths.append({rotation_path});
1323 }
1324 break;
1325
1326 case TFM_ROTATION:
1327 case TFM_TRACKBALL:
1328 if ((toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
1329 rna_paths.append({rotation_path});
1330 }
1331 break;
1332
1333 case TFM_RESIZE:
1334 if ((toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
1335 rna_paths.append({"scale"});
1336 }
1337 break;
1338
1339 default:
1340 break;
1341 }
1342 return rna_paths;
1343}
1344
1346 Scene *scene,
1347 Object *ob,
1348 short targetless_ik,
1349 const eTfmMode tmode,
1350 const bool transforming_more_than_one_bone)
1351{
1352
1353 bPose *pose = ob->pose;
1354 LISTBASE_FOREACH (bPoseChannel *, pchan, &pose->chanbase) {
1355 if ((pchan->bone->flag & BONE_TRANSFORM) == 0 &&
1356 !((pose->flag & POSE_MIRROR_EDIT) && (pchan->bone->flag & BONE_TRANSFORM_MIRROR)))
1357 {
1358 continue;
1359 }
1360
1361 blender::Vector<RNAPath> rna_paths;
1363 eRotationModes(pchan->rotmode));
1364
1366 const bool is_connected = pchan->bone->parent != nullptr &&
1367 (pchan->bone->flag & BONE_CONNECTED);
1369 scene->toolsettings,
1370 rotation_path,
1371 targetless_ik,
1372 is_connected,
1373 transforming_more_than_one_bone);
1374 }
1375 else {
1376 rna_paths = {{"location"}, {rotation_path}, {"scale"}};
1377 }
1378
1380 C, scene, ob, pchan, rna_paths.as_span(), targetless_ik);
1381 }
1382}
1383
1385{
1386 if (t->mode == TFM_BONESIZE) {
1387 /* Handle the exception where for TFM_BONESIZE in edit mode we pretend to be
1388 * in pose mode (to use bone orientation matrix),
1389 * in that case we have to do mirroring as well. */
1391 Object *ob = tc->poseobj;
1392 bArmature *arm = static_cast<bArmature *>(ob->data);
1393 if (ob->mode == OB_MODE_EDIT) {
1394 if (arm->flag & ARM_MIRROR_EDIT) {
1395 if (t->state != TRANS_CANCEL) {
1397 }
1398 else {
1399 restoreBones(tc);
1400 }
1401 }
1402 }
1403 else if (ob->mode == OB_MODE_POSE) {
1404 /* Actually support #TFM_BONESIZE in pose-mode as well. */
1406 bPose *pose = ob->pose;
1407 if (arm->flag & ARM_MIRROR_EDIT || pose->flag & POSE_MIRROR_EDIT) {
1409 }
1410 }
1411 }
1412 }
1413 else {
1414 GSet *motionpath_updates = BLI_gset_ptr_new("motionpath updates");
1415
1417 Object *ob = tc->poseobj;
1418 bPose *pose = ob->pose;
1419
1420 if (pose->flag & POSE_MIRROR_EDIT) {
1421 if (t->state != TRANS_CANCEL) {
1423 }
1424 else {
1426 }
1427 }
1428
1429 /* If animtimer is running, and the object already has animation data,
1430 * check if the auto-record feature means that we should record 'samples'
1431 * (i.e. un-editable animation values).
1432 *
1433 * Context is needed for keying set poll() functions.
1434 */
1435
1436 /* TODO: autokeyframe calls need some setting to specify to add samples
1437 * (FPoints) instead of keyframes? */
1438 if ((t->animtimer) && (t->context) && blender::animrig::is_autokey_on(t->scene)) {
1439
1440 /* XXX: this currently doesn't work, since flags aren't set yet! */
1441 int targetless_ik = (t->flag & T_AUTOIK);
1442
1443 animrecord_check_state(t, &ob->id);
1444 autokeyframe_pose(t->context, t->scene, ob, targetless_ik, t->mode, t->data_len_all > 1);
1445 }
1446
1447 if (motionpath_need_update_pose(t->scene, ob)) {
1448 BLI_gset_insert(motionpath_updates, ob);
1449 }
1450
1452 }
1453
1454 /* Update motion paths once for all transformed bones in an object. */
1455 GSetIterator gs_iter;
1456 GSET_ITER (gs_iter, motionpath_updates) {
1457 Object *ob = static_cast<Object *>(BLI_gsetIterator_getKey(&gs_iter));
1459 }
1460 BLI_gset_free(motionpath_updates, nullptr);
1461 }
1462}
1463
1466/* -------------------------------------------------------------------- */
1470static void bone_children_clear_transflag(int mode, short around, ListBase *lb)
1471{
1472 Bone *bone = static_cast<Bone *>(lb->first);
1473
1474 for (; bone; bone = bone->next) {
1475 if ((bone->flag & BONE_HINGE) && (bone->flag & BONE_CONNECTED)) {
1477 }
1478 else if ((bone->flag & BONE_TRANSFORM) && ELEM(mode, TFM_ROTATION, TFM_TRACKBALL) &&
1479 (around == V3D_AROUND_LOCAL_ORIGINS))
1480 {
1481 bone->flag |= BONE_TRANSFORM_CHILD;
1482 }
1483 else {
1484 bone->flag &= ~BONE_TRANSFORM;
1485 }
1486
1487 bone_children_clear_transflag(mode, around, &bone->childbase);
1488 }
1489}
1490
1491void transform_convert_pose_transflags_update(Object *ob, const int mode, const short around)
1492{
1493 bArmature *arm = static_cast<bArmature *>(ob->data);
1494 Bone *bone;
1495
1496 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
1497 bone = pchan->bone;
1498 if (PBONE_VISIBLE(arm, bone)) {
1499 if (bone->flag & BONE_SELECTED) {
1500 bone->flag |= BONE_TRANSFORM;
1501 }
1502 else {
1503 bone->flag &= ~BONE_TRANSFORM;
1504 }
1505
1506 bone->flag &= ~BONE_HINGE_CHILD_TRANSFORM;
1507 bone->flag &= ~BONE_TRANSFORM_CHILD;
1508 }
1509 else {
1510 bone->flag &= ~BONE_TRANSFORM;
1511 }
1512 }
1513
1514 /* Make sure no bone can be transformed when a parent is transformed. */
1515 /* Since pchans are depsgraph sorted, the parents are in beginning of list. */
1517 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
1518 bone = pchan->bone;
1519 if (bone->flag & BONE_TRANSFORM) {
1520 bone_children_clear_transflag(mode, around, &bone->childbase);
1521 }
1522 }
1523 }
1524}
1525
1527{
1528 bPoseChannel *chanlist[256];
1530 int segcount, apply = 0;
1531
1532 /* Now we got a difficult situation... we have to find the
1533 * target-less IK pchans, and apply transformation to the all
1534 * pchans that were in the chain. */
1535
1536 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
1537 data = has_targetless_ik(pchan);
1538 if (data && (data->flag & CONSTRAINT_IK_AUTO)) {
1539
1540 /* Fill the array with the bones of the chain (`armature.cc` does same, keep it synced). */
1541 segcount = 0;
1542
1543 /* Exclude tip from chain? */
1544 bPoseChannel *parchan = (data->flag & CONSTRAINT_IK_TIP) ? pchan : pchan->parent;
1545
1546 /* Find the chain's root & count the segments needed. */
1547 for (; parchan; parchan = parchan->parent) {
1548 chanlist[segcount] = parchan;
1549 segcount++;
1550
1551 if (segcount == data->rootbone || segcount > 255) {
1552 break; /* 255 is weak. */
1553 }
1554 }
1555 for (; segcount; segcount--) {
1556 Bone *bone;
1557 float mat[4][4];
1558
1559 /* `pose_mat(b) = pose_mat(b-1) * offs_bone * channel * constraint * IK`. */
1560 /* We put in channel the entire result of: `mat = (channel * constraint * IK)`. */
1561 /* `pose_mat(b) = pose_mat(b-1) * offs_bone * mat`. */
1562 /* `mat = pose_mat(b) * inv(pose_mat(b-1) * offs_bone)`. */
1563
1564 parchan = chanlist[segcount - 1];
1565 bone = parchan->bone;
1566 bone->flag |= BONE_TRANSFORM; /* Ensures it gets an auto key inserted. */
1567
1568 BKE_armature_mat_pose_to_bone(parchan, parchan->pose_mat, mat);
1569 /* Apply and decompose, doesn't work for constraints or non-uniform scale well. */
1570 {
1571 float rmat3[3][3], qrmat[3][3], imat3[3][3], smat[3][3];
1572
1573 copy_m3_m4(rmat3, mat);
1574 /* Make sure that our rotation matrix only contains rotation and not scale. */
1575 normalize_m3(rmat3);
1576
1577 /* Rotation. */
1578 /* #22409 is partially caused by this, as slight numeric error introduced during
1579 * the solving process leads to locked-axis values changing. However, we cannot modify
1580 * the values here, or else there are huge discrepancies between IK-solver (interactive)
1581 * and applied poses. */
1582 BKE_pchan_mat3_to_rot(parchan, rmat3, false);
1583
1584 /* For size, remove rotation. */
1585 /* Causes problems with some constraints (so apply only if needed). */
1586 if (data->flag & CONSTRAINT_IK_STRETCH) {
1587 BKE_pchan_rot_to_mat3(parchan, qrmat);
1588 invert_m3_m3(imat3, qrmat);
1589 mul_m3_m3m3(smat, rmat3, imat3);
1590 mat3_to_size(parchan->size, smat);
1591 }
1592
1593 /* Causes problems with some constraints (e.g. child-of), so disable this
1594 * as it is IK shouldn't affect location directly. */
1595 // copy_v3_v3(parchan->loc, mat[3]);
1596 }
1597 }
1598
1599 apply = 1;
1600 data->flag &= ~CONSTRAINT_IK_AUTO;
1601 }
1602 }
1603
1604 return apply;
1605}
1606
1608static void pose_grab_with_ik_clear(Main *bmain, Object *ob)
1609{
1611 bConstraint *con, *next;
1612 bool relations_changed = false;
1613
1614 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
1615 /* Clear all temporary lock flags. */
1617
1618 pchan->constflag &= ~(PCHAN_HAS_IK | PCHAN_HAS_NO_TARGET);
1619
1620 /* Remove all temporary IK-constraints added. */
1621 for (con = static_cast<bConstraint *>(pchan->constraints.first); con; con = next) {
1622 next = con->next;
1623 if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
1624 data = static_cast<bKinematicConstraint *>(con->data);
1625 if (data->flag & CONSTRAINT_IK_TEMP) {
1626 relations_changed = true;
1627
1628 /* `iTaSC` needs clear for removed constraints. */
1629 BIK_clear_data(ob->pose);
1630
1631 BLI_remlink(&pchan->constraints, con);
1632 MEM_freeN(con->data);
1633 MEM_freeN(con);
1634 continue;
1635 }
1636 pchan->constflag |= PCHAN_HAS_IK;
1637 if (data->tar == nullptr || (data->tar->type == OB_ARMATURE && data->subtarget[0] == 0)) {
1638 pchan->constflag |= PCHAN_HAS_NO_TARGET;
1639 }
1640 }
1641 }
1642 }
1643
1644 if (relations_changed) {
1645 /* TODO(sergey): Consider doing partial update only. */
1647 }
1648}
1649
1651{
1652 Object *ob;
1653
1654 if (t->mode == TFM_BONESIZE) {
1655 /* Handle the exception where for TFM_BONESIZE in edit mode we pretend to be
1656 * in pose mode (to use bone orientation matrix),
1657 * in that case we don't do operations like auto-keyframing. */
1659 ob = tc->poseobj;
1661 }
1662 }
1663 else {
1664 const bool canceled = (t->state == TRANS_CANCEL);
1665
1666 if (blender::animrig::is_autokey_on(t->scene) && !canceled) {
1669 for (int i = 0; i < tc->data_len; i++) {
1670 const TransData *td = &tc->data[i];
1671 objects.append(td->ob);
1672 }
1673 }
1675 }
1676
1677 GSet *motionpath_updates = BLI_gset_ptr_new("motionpath updates");
1678
1680 short targetless_ik = 0;
1681
1682 ob = tc->poseobj;
1683
1684 if ((t->flag & T_AUTOIK) && (t->options & CTX_AUTOCONFIRM)) {
1685 /* When running transform non-interactively (operator exec),
1686 * we need to update the pose otherwise no updates get called during
1687 * transform and the auto-IK is not applied. see #26164. */
1688 Object *pose_ob = tc->poseobj;
1689 BKE_pose_where_is(t->depsgraph, t->scene, pose_ob);
1690 }
1691
1692 /* Set BONE_TRANSFORM flags for auto-key, gizmo draw might have changed them. */
1693 if (!canceled && (t->mode != TFM_DUMMY)) {
1695 }
1696
1697 /* If target-less IK grabbing, we calculate the pchan transforms and clear flag. */
1698 if (!canceled && t->mode == TFM_TRANSLATION) {
1699 targetless_ik = apply_targetless_ik(ob);
1700 }
1701 else {
1702 /* Not forget to clear the auto flag. */
1703 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
1705 if (data) {
1706 data->flag &= ~CONSTRAINT_IK_AUTO;
1707 }
1708 }
1709 }
1710
1711 if (t->mode == TFM_TRANSLATION) {
1712 Main *bmain = CTX_data_main(t->context);
1713 pose_grab_with_ik_clear(bmain, ob);
1714 }
1715
1716 /* Automatic inserting of keys and unkeyed tagging -
1717 * only if transform wasn't canceled (or #TFM_DUMMY). */
1718 if (!canceled && (t->mode != TFM_DUMMY)) {
1719 autokeyframe_pose(C, t->scene, ob, targetless_ik, t->mode, t->data_len_all > 1);
1721 }
1722 else {
1724 }
1725
1726 if (t->mode != TFM_DUMMY && motionpath_need_update_pose(t->scene, ob)) {
1727 BLI_gset_insert(motionpath_updates, ob);
1728 }
1729 }
1730
1731 /* Update motion paths once for all transformed bones in an object. */
1732 GSetIterator gs_iter;
1733 GSET_ITER (gs_iter, motionpath_updates) {
1736 ob = static_cast<Object *>(BLI_gsetIterator_getKey(&gs_iter));
1737 ED_pose_recalculate_paths(C, t->scene, ob, range);
1738 }
1739 BLI_gset_free(motionpath_updates, nullptr);
1740 }
1741}
1742
1746 /*flags*/ (T_EDIT | T_POINTS),
1747 /*create_trans_data*/ createTransArmatureVerts,
1748 /*recalc_data*/ recalcData_edit_armature,
1749 /*special_aftertrans_update*/ nullptr,
1750};
1751
1753 /*flags*/ 0,
1754 /*create_trans_data*/ createTransPose,
1755 /*recalc_data*/ recalcData_pose,
1756 /*special_aftertrans_update*/ special_aftertrans_update__pose,
1757};
Functions and classes to work with Actions.
C++ functions to deal with Armature collections (i.e. the successor of bone layers).
Functions to insert, delete or modify keyframes.
Helper functions for animation to interact with the RNA system.
void BIK_clear_data(struct bPose *pose)
Blender kernel action and pose functionality.
bPoseChannel * BKE_pose_channel_find_name(const bPose *pose, const char *name)
bPoseChannel * BKE_pose_channel_get_mirrored(const bPose *pose, const char *name) ATTR_WARN_UNUSED_RESULT
bool BKE_pose_is_bonecoll_visible(const bArmature *arm, const bPoseChannel *pchan) ATTR_WARN_UNUSED_RESULT
void BKE_pchan_rot_to_mat3(const bPoseChannel *pchan, float r_mat[3][3])
Definition armature.cc:2334
bArmature * BKE_armature_from_object(Object *ob)
Definition armature.cc:522
void BKE_pchan_apply_mat4(bPoseChannel *pchan, const float mat[4][4], bool use_compat)
Definition armature.cc:2358
void BKE_armature_mat_pose_to_bone(bPoseChannel *pchan, const float inmat[4][4], float outmat[4][4])
Definition armature.cc:2249
void BKE_pchan_to_mat4(const bPoseChannel *pchan, float r_chanmat[4][4])
Definition armature.cc:2837
#define PBONE_VISIBLE(arm, bone)
void BKE_pose_where_is(Depsgraph *depsgraph, Scene *scene, Object *ob)
Definition armature.cc:2941
void BKE_bone_parent_transform_calc_from_pchan(const bPoseChannel *pchan, BoneParentTransform *r_bpt)
Definition armature.cc:2039
void BKE_pchan_mat3_to_rot(bPoseChannel *pchan, const float mat[3][3], bool use_compat)
Definition armature.cc:2312
struct bConstraint * BKE_constraint_add_for_pose(struct Object *ob, struct bPoseChannel *pchan, const char *name, short type)
Main * CTX_data_main(const bContext *C)
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:125
#define BLI_assert(a)
Definition BLI_assert.h:50
struct GSet GSet
Definition BLI_ghash.h:341
GSet * BLI_gset_ptr_new(const char *info)
void BLI_gset_insert(GSet *gs, void *key)
Definition BLI_ghash.c:959
BLI_INLINE void * BLI_gsetIterator_getKey(GSetIterator *gsi)
Definition BLI_ghash.h:459
#define GSET_ITER(gs_iter_, gset_)
Definition BLI_ghash.h:472
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
Definition BLI_ghash.c:1034
#define LISTBASE_FOREACH(type, var, list)
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:130
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void pseudoinverse_m3_m3(float inverse[3][3], const float mat[3][3], float epsilon)
void copy_m3_m3(float m1[3][3], const float m2[3][3])
void copy_m3_m4(float m1[3][3], const float m2[4][4])
#define PSEUDOINVERSE_EPSILON
bool invert_m3_m3(float inverse[3][3], const float mat[3][3])
void unit_m4(float m[4][4])
Definition rct.c:1127
void normalize_m3(float R[3][3]) ATTR_NONNULL()
void mul_v3_m4v3(float r[3], const float mat[4][4], const float vec[3])
bool invert_m4(float mat[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])
float angle_compat_rad(float angle, float angle_compat)
void rotation_between_vecs_to_quat(float q[4], const float v1[3], const float v2[3])
void mul_qt_v3(const float q[4], float r[3])
void copy_qt_qt(float q[4], const float a[4])
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
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 float normalize_v3(float n[3])
#define ELEM(...)
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_relations_tag_update(Main *bmain)
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1041
@ MOTIONPATH_BAKE_HAS_PATHS
eRotationModes
@ ROT_MODE_AXISANGLE
@ BONE_IK_NO_YDOF_TEMP
@ BONE_IK_NO_XDOF_TEMP
@ BONE_IK_NO_ZDOF_TEMP
@ PCHAN_HAS_NO_TARGET
@ PCHAN_HAS_IK
@ POSE_AUTO_IK
@ POSE_MIRROR_EDIT
@ POSE_MIRROR_RELATIVE
@ BONE_ROOTSEL
@ BONE_SELECTED
@ BONE_TRANSFORM
@ BONE_EDITMODE_LOCKED
@ BONE_TRANSFORM_MIRROR
@ BONE_NO_LOCAL_LOCATION
@ BONE_TRANSFORM_CHILD
@ BONE_TIPSEL
@ BONE_CONNECTED
@ BONE_HINGE
@ BONE_HINGE_CHILD_TRANSFORM
@ ARM_MIRROR_EDIT
@ ARM_RESTPOS
@ CONSTRAINT_OFF
@ CONSTRAINT_DISABLE
@ CONSTRAINT_IK_TEMP
@ CONSTRAINT_IK_POS
@ CONSTRAINT_IK_AUTO
@ CONSTRAINT_IK_STRETCH
@ CONSTRAINT_IK_TIP
@ CONSTRAINT_TYPE_KINEMATIC
@ OB_MODE_EDIT
@ OB_MODE_POSE
@ OB_LOCK_ROTZ
@ OB_LOCK_ROT
@ OB_LOCK_ROTX
@ OB_LOCK_ROTY
@ OB_LOCK_LOC
@ OB_LOCK_SCALE
@ OB_ARMATURE
@ SCE_XFORM_AXIS_ALIGN
@ AUTOKEY_FLAG_INSERTNEEDED
@ V3D_AROUND_CURSOR
@ V3D_AROUND_LOCAL_ORIGINS
@ V3D_ORIENT_GIMBAL
ePosePathCalcRange
@ POSE_PATH_CALC_RANGE_CURRENT_FRAME
@ POSE_PATH_CALC_RANGE_CHANGED
#define EBONE_VISIBLE(arm, ebone)
eTfmMode
@ TFM_RESIZE
@ TFM_BONESIZE
@ TFM_ROTATION
@ TFM_BONE_ENVELOPE
@ TFM_BONE_ROLL
@ TFM_TRANSLATION
@ TFM_BONE_ENVELOPE_DIST
@ TFM_DUMMY
@ TFM_TRACKBALL
Read Guarded memory(de)allocation.
void ANIM_deselect_keys_in_animation_editors(bContext *C)
Definition anim_deps.cc:472
float ED_armature_ebone_roll_to_vector(const EditBone *bone, const float align_axis[3], const bool axis_only)
void ED_armature_edit_transform_mirror_update(Object *obedit)
void ED_armature_ebone_to_mat3(EditBone *ebone, float r_mat[3][3])
EditBone * ED_armature_ebone_get_mirrored(const ListBase *edbo, EditBone *ebo)
void append(const T &value)
void append_non_duplicates(const T &value)
Span< T > as_span() const
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
size_t(* MEM_allocN_len)(const void *vmemh)
Definition mallocn.cc:36
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
static ulong * next
bool is_autokey_on(const Scene *scene)
bool autokeyframe_cfra_can_key(const Scene *scene, ID *id)
StringRef get_rotation_mode_path(eRotationModes rotation_mode)
Definition anim_rna.cc:73
bool is_keying_flag(const Scene *scene, eKeying_Flag flag)
void autokeyframe_pose_channel(bContext *C, Scene *scene, Object *ob, bPoseChannel *pose_channel, Span< RNAPath > rna_paths, short targetless_ik)
void ED_pose_recalculate_paths(bContext *C, Scene *scene, Object *ob, ePosePathCalcRange range)
Definition pose_edit.cc:152
float rotscale_mat[4][4]
char name[64]
float bone_mat[3][3]
struct Bone * next
ListBase childbase
float oldlength
float tail[3]
EditBone * parent
float zwidth
float length
float xwidth
float rad_tail
float rad_head
float head[3]
void * first
struct bPose * pose
struct PoseInitData_Mirror::@566 orig
TransCustomData type
Definition transform.hh:425
TransCustomDataContainer custom
Definition transform.hh:501
TransData * data
Definition transform.hh:445
float axismtx_gimbal[3][3]
float smtx[3][3]
float axismtx[3][3]
float mtx[3][3]
TransDataExtension * ext
bConstraint * con
eTfmMode mode
Definition transform.hh:517
short around
Definition transform.hh:580
int data_len_all
Definition transform.hh:510
wmTimer * animtimer
Definition transform.hh:657
ReportList * reports
Definition transform.hh:661
eTState state
Definition transform.hh:527
Scene * scene
Definition transform.hh:654
eTFlag flag
Definition transform.hh:523
int orient_type_mask
Definition transform.hh:619
Depsgraph * depsgraph
Definition transform.hh:653
bContext * context
Definition transform.hh:649
eTContext options
Definition transform.hh:521
ListBase * edbo
struct bConstraint * next
struct Bone * bone
struct bPoseChannel * parent
struct Object * custom
float constinv[4][4]
float pose_mat[4][4]
ListBase chanbase
bAnimVizSettings avs
@ CTX_AUTOCONFIRM
Definition transform.hh:78
@ T_AUTOIK
Definition transform.hh:108
@ T_POINTS
Definition transform.hh:93
@ T_EDIT
Definition transform.hh:91
@ TRANS_CANCEL
Definition transform.hh:210
#define FOREACH_TRANS_DATA_CONTAINER(t, th)
Definition transform.hh:854
void transform_autoik_update(TransInfo *t, short mode)
void transform_around_single_fallback(TransInfo *t)
void animrecord_check_state(TransInfo *t, ID *id)
bool constraints_list_needinv(TransInfo *t, ListBase *list)
conversion and adaptation of different datablocks to a common struct.
static void autokeyframe_pose(bContext *C, Scene *scene, Object *ob, short targetless_ik, const eTfmMode tmode, const bool transforming_more_than_one_bone)
static bool motionpath_need_update_pose(Scene *scene, Object *ob)
static void restoreMirrorPoseBones(TransDataContainer *tc)
static void recalcData_pose(TransInfo *t)
static void pose_mirror_info_init(PoseInitData_Mirror *pid, bPoseChannel *pchan, bPoseChannel *pchan_orig, bool is_mirror_relative)
static void pose_mirror_info_restore(const PoseInitData_Mirror *pid)
static void pose_transform_mirror_update(TransInfo *t, TransDataContainer *tc, Object *ob)
static void update_deg_with_temporary_ik(Main *bmain, Object *ob)
static void bone_children_clear_transflag(int mode, short around, ListBase *lb)
static void recalcData_edit_armature(TransInfo *t)
static short pose_grab_with_ik(Main *bmain, Object *ob)
static short pose_grab_with_ik_add(bPoseChannel *pchan)
static short apply_targetless_ik(Object *ob)
static void restoreBones(TransDataContainer *tc)
static void createTransPose(bContext *, TransInfo *t)
static blender::Vector< RNAPath > get_affected_rna_paths_from_transform_mode(const eTfmMode tmode, ToolSettings *toolsettings, const blender::StringRef rotation_path, const bool targetless_ik, const bool is_connected, const bool transforming_more_than_one_bone)
static short pose_grab_with_ik_children(bPose *pose, Bone *bone)
static void special_aftertrans_update__pose(bContext *C, TransInfo *t)
static bKinematicConstraint * has_targetless_ik(bPoseChannel *pchan)
static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, TransData *td)
static void createTransArmatureVerts(bContext *, TransInfo *t)
TransConvertTypeInfo TransConvertType_EditArmature
static void pose_grab_with_ik_clear(Main *bmain, Object *ob)
TransConvertTypeInfo TransConvertType_Pose
void transform_convert_pose_transflags_update(Object *ob, const int mode, const short around)
static bConstraint * add_temporary_ik_constraint(bPoseChannel *pchan, bKinematicConstraint *targetless_con)
@ TD_PBONE_LOCAL_MTX_P
@ TD_PBONE_LOCAL_MTX_C
@ TD_SELECTED
@ TD_NO_LOC
@ TD_NOCENTER
bool gimbal_axis_pose(Object *ob, const bPoseChannel *pchan, float gmat[3][3])
void transform_snap_project_individual_apply(TransInfo *t)