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