Blender V5.0
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->flag & POSE_SELECTED) || (pchan->bone->flag & 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->flag & POSE_SELECTED) || (parent->bone->flag & 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 TransInfo *t, bPoseChannel *pchan, Object *ob, TransData *td, TransDataExtension *td_ext)
394{
395 Bone *bone = pchan->bone;
396 float pmat[3][3], omat[3][3];
397 float cmat[3][3], tmat[3][3];
398
399 const bArmature *arm = static_cast<bArmature *>(ob->data);
402 copy_v3_v3(td_ext->center_no_override, pchan->pose_mat[3]);
403 }
404 else {
406 }
407
408 td->flag = TD_SELECTED;
410 td->flag |= TD_NOCENTER;
411 }
412
414 td->flag |= TD_NOCENTER;
415 td->flag |= TD_NO_LOC;
416 }
417
418 td->extra = pchan;
419 td->protectflag = pchan->protectflag;
420
421 td->loc = pchan->loc;
422 copy_v3_v3(td->iloc, pchan->loc);
423
424 td_ext->scale = pchan->scale;
425 copy_v3_v3(td_ext->iscale, pchan->scale);
426
427 if (pchan->rotmode > 0) {
428 td_ext->rot = pchan->eul;
429 td_ext->rotAxis = nullptr;
430 td_ext->rotAngle = nullptr;
431 td_ext->quat = nullptr;
432
433 copy_v3_v3(td_ext->irot, pchan->eul);
434 }
435 else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
436 td_ext->rot = nullptr;
437 td_ext->rotAxis = pchan->rotAxis;
438 td_ext->rotAngle = &pchan->rotAngle;
439 td_ext->quat = nullptr;
440
441 td_ext->irotAngle = pchan->rotAngle;
442 copy_v3_v3(td_ext->irotAxis, pchan->rotAxis);
443 }
444 else {
445 td_ext->rot = nullptr;
446 td_ext->rotAxis = nullptr;
447 td_ext->rotAngle = nullptr;
448 td_ext->quat = pchan->quat;
449
450 copy_qt_qt(td_ext->iquat, pchan->quat);
451 }
452 td_ext->rotOrder = pchan->rotmode;
453
454 /* Proper way to get parent transform + our own transform + constraints transform. */
455 copy_m3_m4(omat, ob->object_to_world().ptr());
456
457 {
459 float rpmat[3][3];
460
461 /* Not using the pchan->custom_tx here because we need the transformation to be
462 * relative to the actual bone being modified, not it's visual representation. */
464 if (t->mode == TFM_TRANSLATION) {
465 copy_m3_m4(pmat, bpt.loc_mat);
466 }
467 else {
468 copy_m3_m4(pmat, bpt.rotscale_mat);
469 }
470
471 /* Grrr! Exceptional case: When translating pose bones that are either Hinge or NoLocal,
472 * and want align snapping, we just need both loc_mat and rotscale_mat.
473 * So simply always store rotscale mat in td->ext, and always use it to apply rotations...
474 * Ugly to need such hacks! :/ */
475 copy_m3_m4(rpmat, bpt.rotscale_mat);
476
477 if (constraints_list_needinv(t, &pchan->constraints)) {
478 copy_m3_m4(tmat, pchan->constinv);
479 invert_m3_m3(cmat, tmat);
480 mul_m3_series(td->mtx, cmat, omat, pmat);
481 mul_m3_series(td_ext->r_mtx, cmat, omat, rpmat);
482 }
483 else {
484 mul_m3_series(td->mtx, omat, pmat);
485 mul_m3_series(td_ext->r_mtx, omat, rpmat);
486 }
487 invert_m3_m3(td_ext->r_smtx, td_ext->r_mtx);
488 }
489
491
492 /* Exceptional case: rotate the pose bone which also applies transformation
493 * when a parentless bone has #BONE_NO_LOCAL_LOCATION []. */
495 {
496 if (pchan->parent) {
497 /* Same as `td->smtx` but without `pchan->bone->bone_mat`. */
499 mul_m3_m3m3(td_ext->l_smtx, pchan->bone->bone_mat, td->smtx);
500 }
501 else {
503 }
504 }
505
506 /* For `axismtx` we use the bone's own transform. */
508 mul_m3_m3m3(td->axismtx, omat, pmat);
510
511 if (t->orient_type_mask & (1 << V3D_ORIENT_GIMBAL)) {
512 if (!gimbal_axis_pose(ob, pchan, td_ext->axismtx_gimbal)) {
513 copy_m3_m3(td_ext->axismtx_gimbal, td->axismtx);
514 }
515 }
516
517 if (t->mode == TFM_BONE_ENVELOPE_DIST) {
518 td->loc = nullptr;
519 td->val = &bone->dist;
520 td->ival = bone->dist;
521 }
522 else if (t->mode == TFM_BONESIZE) {
523 /* Abusive storage of scale in the loc pointer :). */
524 td->loc = &bone->xwidth;
525 copy_v3_v3(td->iloc, td->loc);
526 td->val = nullptr;
527 }
528
529 /* In this case we can do target-less IK grabbing. */
530 if (t->mode == TFM_TRANSLATION) {
532 if (data) {
533 if (data->flag & CONSTRAINT_IK_TIP) {
534 copy_v3_v3(data->grabtarget, pchan->pose_tail);
535 }
536 else {
537 copy_v3_v3(data->grabtarget, pchan->pose_head);
538 }
539 td->loc = data->grabtarget;
540 copy_v3_v3(td->iloc, td->loc);
541
542 data->flag |= CONSTRAINT_IK_AUTO;
543
544 /* Add a temporary auto IK constraint here, as we will only temporarily active this
545 * targetless bone during transform. (Targetless IK constraints are treated as if they are
546 * disabled unless they are transformed).
547 * Only do this for targetless IK though, AutoIK already added a constraint in
548 * pose_grab_with_ik_add() beforehand. */
549 if ((data->flag & CONSTRAINT_IK_TEMP) == 0) {
551 Main *bmain = CTX_data_main(t->context);
553 }
554
555 /* Only object matrix correction. */
556 copy_m3_m3(td->mtx, omat);
558 }
559 }
560
561 /* Store reference to first constraint. */
562 td->con = static_cast<bConstraint *>(pchan->constraints.first);
563}
564
565static void createTransPose(bContext * /*C*/, TransInfo *t)
566{
567 Main *bmain = CTX_data_main(t->context);
568
569 t->data_len_all = 0;
570
571 bool has_translate_rotate_buf[2] = {false, false};
572 bool *has_translate_rotate = (t->mode == TFM_TRANSLATION) ? has_translate_rotate_buf : nullptr;
573
575 Object *ob = tc->poseobj;
576 bPose *pose = ob->pose;
577
578 bArmature *arm;
579
580 /* Check validity of state. */
581 arm = BKE_armature_from_object(tc->poseobj);
582 if ((arm == nullptr) || (pose == nullptr)) {
583 continue;
584 }
585
586 const bool mirror = ((pose->flag & POSE_MIRROR_EDIT) != 0);
587
588 /* Set flags. */
590
591 /* Now count, and check if we have autoIK or have to switch from translate to rotate. */
592 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
593 Bone *bone = pchan->bone;
594 if (!(pchan->runtime.flag & POSE_RUNTIME_TRANSFORM)) {
595 continue;
596 }
597
598 tc->data_len++;
599
600 if (has_translate_rotate != nullptr) {
601 if (has_translate_rotate[0] && has_translate_rotate[1]) {
602 continue;
603 }
604
605 if (has_targetless_ik(pchan) == nullptr) {
606 if (pchan->parent && (bone->flag & BONE_CONNECTED)) {
607 if (pchan->runtime.flag & POSE_RUNTIME_HINGE_CHILD_TRANSFORM) {
608 has_translate_rotate[0] = true;
609 }
610 }
611 else {
612 if ((pchan->protectflag & OB_LOCK_LOC) != OB_LOCK_LOC) {
613 has_translate_rotate[0] = true;
614 }
615 }
616 if ((pchan->protectflag & OB_LOCK_ROT) != OB_LOCK_ROT) {
617 has_translate_rotate[1] = true;
618 }
619 }
620 else {
621 has_translate_rotate[0] = true;
622 }
623 }
624 }
625
626 if (tc->data_len == 0) {
627 continue;
628 }
629
630 if (arm->flag & ARM_RESTPOS) {
631 if (ELEM(t->mode, TFM_DUMMY, TFM_BONESIZE) == 0) {
632 BKE_report(t->reports, RPT_ERROR, "Cannot change Pose when 'Rest Position' is enabled");
633 tc->data_len = 0;
634 continue;
635 }
636 }
637
638 if (mirror) {
639 int total_mirrored = 0;
640 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
641 /* Clear the MIRROR flag from previous runs. */
642 pchan->bone->flag &= ~BONE_TRANSFORM_MIRROR;
643
644 if ((pchan->runtime.flag & POSE_RUNTIME_TRANSFORM) &&
645 BKE_pose_channel_get_mirrored(ob->pose, pchan->name))
646 {
647 total_mirrored++;
648 }
649 }
650
652 "PoseInitData_Mirror");
653
654 /* Trick to terminate iteration. */
655 pid[total_mirrored].pchan = nullptr;
656
657 tc->custom.type.data = pid;
658 tc->custom.type.use_free = true;
659 }
660 }
661
663 if (tc->data_len == 0) {
664 continue;
665 }
666 Object *ob = tc->poseobj;
667 TransData *td;
669
670 PoseInitData_Mirror *pid = static_cast<PoseInitData_Mirror *>(tc->custom.type.data);
671 int pid_index = 0;
672 bPose *pose = ob->pose;
673
674 if (pose == nullptr) {
675 continue;
676 }
677
678 const bool mirror = ((pose->flag & POSE_MIRROR_EDIT) != 0);
679 const bool is_mirror_relative = ((pose->flag & POSE_MIRROR_RELATIVE) != 0);
680
681 /* We also allow non-active objects to be transformed, in weight-paint. */
682 tc->poseobj = ob;
683
684 /* Initialize trans data. */
685 td = tc->data = MEM_calloc_arrayN<TransData>(tc->data_len, "TransPoseBone");
686 tdx = tc->data_ext = MEM_calloc_arrayN<TransDataExtension>(tc->data_len, "TransPoseBoneExt");
687
688 if (mirror) {
689 LISTBASE_FOREACH (bPoseChannel *, pchan, &pose->chanbase) {
690 if (pchan->runtime.flag & POSE_RUNTIME_TRANSFORM) {
691 bPoseChannel *pchan_mirror = BKE_pose_channel_get_mirrored(ob->pose, pchan->name);
692 if (pchan_mirror) {
693 pchan_mirror->bone->flag |= BONE_TRANSFORM_MIRROR;
694 pose_mirror_info_init(&pid[pid_index], pchan_mirror, pchan, is_mirror_relative);
695 pid_index++;
696 }
697 }
698 }
699 }
700
701 /* Do we need to add temporal IK chains? */
702 if ((pose->flag & POSE_AUTO_IK) && t->mode == TFM_TRANSLATION) {
703 if (pose_grab_with_ik(bmain, ob)) {
704 t->flag |= T_AUTOIK;
705 has_translate_rotate[0] = true;
706 }
707 }
708
709 /* Use pose channels to fill trans data. */
710 td = tc->data;
711 tdx = tc->data_ext;
712 tdx->center_no_override[0] = 0;
713 tdx->center_no_override[1] = 0;
714 tdx->center_no_override[2] = 0;
715 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
716 if (pchan->runtime.flag & POSE_RUNTIME_TRANSFORM) {
717 add_pose_transdata(t, pchan, ob, td++, tdx++);
718 }
719 }
720
721 if (td != (tc->data + tc->data_len)) {
722 BKE_report(t->reports, RPT_DEBUG, "Bone selection count error");
724 }
725 }
726
727 /* Initialize initial auto=IK chain-length's? */
728 if (t->flag & T_AUTOIK) {
730 }
731
732 /* If there are no translatable bones, do rotation. */
733 if ((t->mode == TFM_TRANSLATION) && !has_translate_rotate[0]) {
734 if (has_translate_rotate[1]) {
735 t->mode = TFM_ROTATION;
736 }
737 else {
738 t->mode = TFM_RESIZE;
739 }
740 }
741}
742
744{
745 t->data_len_all = 0;
746
748 bArmature *arm = static_cast<bArmature *>(tc->obedit->data);
749 ListBase *edbo = arm->edbo;
750 bool mirror = ((arm->flag & ARM_MIRROR_EDIT) != 0);
751 int total_mirrored = 0;
752
753 tc->data_len = 0;
754 LISTBASE_FOREACH (EditBone *, ebo, edbo) {
755 const int data_len_prev = tc->data_len;
756
757 if (blender::animrig::bone_is_visible(arm, ebo) && !(ebo->flag & BONE_EDITMODE_LOCKED)) {
759 if (ebo->flag & BONE_SELECTED) {
760 tc->data_len++;
761 }
762 }
763 else if (t->mode == TFM_BONE_ROLL) {
764 if (ebo->flag & BONE_SELECTED) {
765 tc->data_len++;
766 }
767 }
768 else {
769 if (ebo->flag & BONE_TIPSEL) {
770 tc->data_len++;
771 }
772 if (ebo->flag & BONE_ROOTSEL) {
773 tc->data_len++;
774 }
775 }
776 }
777
778 if (mirror && (data_len_prev < tc->data_len)) {
779 EditBone *eboflip = ED_armature_ebone_get_mirrored(arm->edbo, ebo);
780 if (eboflip) {
781 total_mirrored++;
782 }
783 }
784 }
785 if (!tc->data_len) {
786 continue;
787 }
788
789 if (mirror) {
790 BoneInitData *bid = MEM_malloc_arrayN<BoneInitData>((total_mirrored + 1), "BoneInitData");
791
792 /* Trick to terminate iteration. */
793 bid[total_mirrored].bone = nullptr;
794
795 tc->custom.type.data = bid;
796 tc->custom.type.use_free = true;
797 }
798 t->data_len_all += tc->data_len;
799 }
800
802 t->data_len_all = -1;
803
805 if (!tc->data_len) {
806 continue;
807 }
808
809 bArmature *arm = static_cast<bArmature *>(tc->obedit->data);
810 ListBase *edbo = arm->edbo;
811 TransData *td, *td_old;
812 float mtx[3][3], smtx[3][3], bonemat[3][3];
813 bool mirror = ((arm->flag & ARM_MIRROR_EDIT) != 0);
814 BoneInitData *bid = static_cast<BoneInitData *>(tc->custom.type.data);
815
816 copy_m3_m4(mtx, tc->obedit->object_to_world().ptr());
818
819 td = tc->data = MEM_calloc_arrayN<TransData>(tc->data_len, "TransEditBone");
820 int i = 0;
821
822 LISTBASE_FOREACH (EditBone *, ebo, edbo) {
823 td_old = td;
824
825 /* (length == 0.0) on extrude, used for scaling radius of bone points. */
826 ebo->oldlength = ebo->length;
827
828 if (blender::animrig::bone_is_visible(arm, ebo) && !(ebo->flag & BONE_EDITMODE_LOCKED)) {
829 if (t->mode == TFM_BONE_ENVELOPE) {
830 if (ebo->flag & BONE_ROOTSEL) {
831 td->val = &ebo->rad_head;
832 td->ival = *td->val;
833
834 copy_v3_v3(td->center, ebo->head);
835 td->flag = TD_SELECTED;
836
837 copy_m3_m3(td->smtx, smtx);
838 copy_m3_m3(td->mtx, mtx);
839
840 td->loc = nullptr;
841
842 td++;
843 }
844 if (ebo->flag & BONE_TIPSEL) {
845 td->val = &ebo->rad_tail;
846 td->ival = *td->val;
847 copy_v3_v3(td->center, ebo->tail);
848 td->flag = TD_SELECTED;
849
850 copy_m3_m3(td->smtx, smtx);
851 copy_m3_m3(td->mtx, mtx);
852
853 td->loc = 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++;
883 }
884 }
885 else if (t->mode == TFM_BONE_ROLL) {
886 if (ebo->flag & BONE_SELECTED) {
887 td->loc = nullptr;
888 td->val = &(ebo->roll);
889 td->ival = ebo->roll;
890
891 copy_v3_v3(td->center, ebo->head);
892 td->flag = TD_SELECTED;
893
894 td++;
895 }
896 }
897 else {
898 if (ebo->flag & BONE_TIPSEL) {
899 copy_v3_v3(td->iloc, ebo->tail);
900
901 /* Don't allow single selected tips to have a modified center,
902 * causes problem with snapping (see #45974).
903 * However, in rotation mode, we want to keep that 'rotate bone around root with
904 * only its tip selected' behavior (see #46325). */
905 if ((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
906 ((t->mode == TFM_ROTATION) || (ebo->flag & BONE_ROOTSEL)))
907 {
908 copy_v3_v3(td->center, ebo->head);
909 }
910 else {
911 copy_v3_v3(td->center, td->iloc);
912 }
913
914 td->loc = ebo->tail;
915 td->flag = TD_SELECTED;
916 if (ebo->flag & BONE_EDITMODE_LOCKED) {
918 }
919
920 copy_m3_m3(td->smtx, smtx);
921 copy_m3_m3(td->mtx, mtx);
922
924
925 if ((ebo->flag & BONE_ROOTSEL) == 0) {
926 td->extra = ebo;
927 td->ival = ebo->roll;
928 }
929
930 td->val = nullptr;
931
932 td++;
933 }
934 if (ebo->flag & BONE_ROOTSEL) {
935 copy_v3_v3(td->iloc, ebo->head);
936 copy_v3_v3(td->center, td->iloc);
937 td->loc = ebo->head;
938 td->flag = TD_SELECTED;
939 if (ebo->flag & BONE_EDITMODE_LOCKED) {
941 }
942
943 copy_m3_m3(td->smtx, smtx);
944 copy_m3_m3(td->mtx, mtx);
945
947
948 td->extra = ebo; /* To fix roll. */
949 td->ival = ebo->roll;
950
951 td->val = nullptr;
952
953 td++;
954 }
955 }
956 }
957
958 if (mirror && (td_old != td)) {
959 EditBone *eboflip = ED_armature_ebone_get_mirrored(arm->edbo, ebo);
960 if (eboflip) {
961 bid[i].bone = eboflip;
962 bid[i].dist = eboflip->dist;
963 bid[i].rad_head = eboflip->rad_head;
964 bid[i].rad_tail = eboflip->rad_tail;
965 bid[i].roll = eboflip->roll;
966 bid[i].xwidth = eboflip->xwidth;
967 bid[i].zwidth = eboflip->zwidth;
968 copy_v3_v3(bid[i].head, eboflip->head);
969 copy_v3_v3(bid[i].tail, eboflip->tail);
970 i++;
971 }
972 }
973 }
974
975 if (mirror) {
976 /* Trick to terminate iteration. */
977 BLI_assert(i + 1 == (MEM_allocN_len(bid) / sizeof(*bid)));
978 bid[i].bone = nullptr;
979 }
980 }
981}
982
984
985/* -------------------------------------------------------------------- */
988
990{
991 bArmature *arm;
992 BoneInitData *bid = static_cast<BoneInitData *>(tc->custom.type.data);
993 EditBone *ebo;
994
995 if (tc->obedit) {
996 arm = static_cast<bArmature *>(tc->obedit->data);
997 }
998 else {
999 BLI_assert(tc->poseobj != nullptr);
1000 arm = static_cast<bArmature *>(tc->poseobj->data);
1001 }
1002
1003 while (bid->bone) {
1004 ebo = bid->bone;
1005
1006 ebo->dist = bid->dist;
1007 ebo->rad_head = bid->rad_head;
1008 ebo->rad_tail = bid->rad_tail;
1009 ebo->roll = bid->roll;
1010 ebo->xwidth = bid->xwidth;
1011 ebo->zwidth = bid->zwidth;
1012 copy_v3_v3(ebo->head, bid->head);
1013 copy_v3_v3(ebo->tail, bid->tail);
1014
1015 if (arm->flag & ARM_MIRROR_EDIT) {
1016 /* Also move connected ebo_child, in case ebo_child's name aren't mirrored properly. */
1017 LISTBASE_FOREACH (EditBone *, ebo_child, arm->edbo) {
1018 if ((ebo_child->flag & BONE_CONNECTED) && (ebo_child->parent == ebo)) {
1019 copy_v3_v3(ebo_child->head, ebo->tail);
1020 ebo_child->rad_head = ebo->rad_tail;
1021 }
1022 }
1023
1024 /* Also move connected parent, in case parent's name isn't mirrored properly. */
1025 if ((ebo->flag & BONE_CONNECTED) && ebo->parent) {
1026 EditBone *parent = ebo->parent;
1027 copy_v3_v3(parent->tail, ebo->head);
1028 parent->rad_tail = ebo->rad_head;
1029 }
1030 }
1031
1032 bid++;
1033 }
1034}
1035
1037{
1038 if (t->state != TRANS_CANCEL) {
1040 }
1041
1043 bArmature *arm = static_cast<bArmature *>(tc->obedit->data);
1044 ListBase *edbo = arm->edbo;
1045 EditBone *ebo, *ebo_parent;
1046 TransData *td = tc->data;
1047 int i;
1048
1049 /* Ensure all bones are correctly adjusted. */
1050 LISTBASE_FOREACH (EditBone *, ebo, edbo) {
1051 ebo_parent = (ebo->flag & BONE_CONNECTED) ? ebo->parent : nullptr;
1052
1053 if (ebo_parent) {
1054 /* If this bone has a parent tip that has been moved. */
1055 if (blender::animrig::bone_is_visible(arm, ebo_parent) && (ebo_parent->flag & BONE_TIPSEL))
1056 {
1057 copy_v3_v3(ebo->head, ebo_parent->tail);
1058 if (t->mode == TFM_BONE_ENVELOPE) {
1059 ebo->rad_head = ebo_parent->rad_tail;
1060 }
1061 }
1062 /* If this bone has a parent tip that has NOT been moved. */
1063 else {
1064 copy_v3_v3(ebo_parent->tail, ebo->head);
1065 if (t->mode == TFM_BONE_ENVELOPE) {
1066 ebo_parent->rad_tail = ebo->rad_head;
1067 }
1068 }
1069 }
1070
1071 /* On extrude bones, oldlength==0.0f, so we scale radius of points. */
1072 ebo->length = len_v3v3(ebo->head, ebo->tail);
1073 if (ebo->oldlength == 0.0f) {
1074 ebo->rad_head = 0.25f * ebo->length;
1075 ebo->rad_tail = 0.10f * ebo->length;
1076 ebo->dist = 0.25f * ebo->length;
1077 if (ebo->parent) {
1078 ebo->rad_head = std::min(ebo->rad_head, ebo->parent->rad_tail);
1079 }
1080 }
1081 else if (t->mode != TFM_BONE_ENVELOPE) {
1082 /* If bones change length, lets do that for the deform distance as well. */
1083 ebo->dist *= ebo->length / ebo->oldlength;
1084 ebo->rad_head *= ebo->length / ebo->oldlength;
1085 ebo->rad_tail *= ebo->length / ebo->oldlength;
1086 ebo->oldlength = ebo->length;
1087
1088 if (ebo_parent) {
1089 ebo_parent->rad_tail = ebo->rad_head;
1090 }
1091 }
1092 }
1093
1095 /* Fix roll. */
1096 for (i = 0; i < tc->data_len; i++, td++) {
1097 if (td->extra) {
1098 float vec[3], up_axis[3];
1099 float qrot[4];
1100 float roll;
1101
1102 ebo = static_cast<EditBone *>(td->extra);
1103
1104 if (t->state == TRANS_CANCEL) {
1105 /* Restore roll. */
1106 ebo->roll = td->ival;
1107 }
1108 else {
1109 copy_v3_v3(up_axis, td->axismtx[2]);
1110
1111 sub_v3_v3v3(vec, ebo->tail, ebo->head);
1112 normalize_v3(vec);
1113 rotation_between_vecs_to_quat(qrot, td->axismtx[1], vec);
1114 mul_qt_v3(qrot, up_axis);
1115
1116 /* Roll has a tendency to flip in certain orientations - #34283, #33974. */
1117 roll = ED_armature_ebone_roll_to_vector(ebo, up_axis, false);
1118 ebo->roll = angle_compat_rad(roll, td->ival);
1119 }
1120 }
1121 }
1122 }
1123
1124 if (arm->flag & ARM_MIRROR_EDIT) {
1125 if (t->state != TRANS_CANCEL) {
1127 }
1128 else {
1129 restoreBones(tc);
1130 }
1131 }
1132 }
1133}
1134
1136
1137/* -------------------------------------------------------------------- */
1140
1146{
1147 float flip_mtx[4][4];
1148 unit_m4(flip_mtx);
1149 flip_mtx[0][0] = -1;
1150
1151 LISTBASE_FOREACH (bPoseChannel *, pchan_orig, &ob->pose->chanbase) {
1152 /* Clear the MIRROR flag from previous runs. */
1153 pchan_orig->bone->flag &= ~BONE_TRANSFORM_MIRROR;
1154 }
1155
1156 bPose *pose = ob->pose;
1157 PoseInitData_Mirror *pid = nullptr;
1158 if ((t->mode != TFM_BONESIZE) && (pose->flag & POSE_MIRROR_RELATIVE)) {
1159 pid = static_cast<PoseInitData_Mirror *>(tc->custom.type.data);
1160 }
1161
1162 TransData *td = tc->data;
1163 for (int i = tc->data_len; i--; td++) {
1164 bPoseChannel *pchan_orig = static_cast<bPoseChannel *>(td->extra);
1166 /* No layer check, correct mirror is more important. */
1167 bPoseChannel *pchan = BKE_pose_channel_get_mirrored(pose, pchan_orig->name);
1168 if (pchan == nullptr) {
1169 continue;
1170 }
1171
1172 /* Also do bbone scaling. */
1173 pchan->bone->xwidth = pchan_orig->bone->xwidth;
1174 pchan->bone->zwidth = pchan_orig->bone->zwidth;
1175
1176 /* We assume X-axis flipping for now. */
1177 pchan->curve_in_x = pchan_orig->curve_in_x * -1;
1178 pchan->curve_out_x = pchan_orig->curve_out_x * -1;
1179 pchan->roll1 = pchan_orig->roll1 * -1; /* XXX? */
1180 pchan->roll2 = pchan_orig->roll2 * -1; /* XXX? */
1181
1182 float pchan_mtx_final[4][4];
1183 BKE_pchan_to_mat4(pchan_orig, pchan_mtx_final);
1184 mul_m4_m4m4(pchan_mtx_final, pchan_mtx_final, flip_mtx);
1185 mul_m4_m4m4(pchan_mtx_final, flip_mtx, pchan_mtx_final);
1186 if (pid) {
1187 mul_m4_m4m4(pchan_mtx_final, pid->offset_mtx, pchan_mtx_final);
1188 }
1189 BKE_pchan_apply_mat4(pchan, pchan_mtx_final, false);
1190
1191 /* Set flag to let auto key-frame know to key-frame the mirrored bone. */
1192 pchan->bone->flag |= BONE_TRANSFORM_MIRROR;
1193
1194 /* In this case we can do target-less IK grabbing. */
1195 if (t->mode == TFM_TRANSLATION) {
1197 if (data == nullptr) {
1198 continue;
1199 }
1200 mul_v3_m4v3(data->grabtarget, flip_mtx, td->loc);
1201 if (pid) {
1202 /* TODO(@germano): Relative Mirror support. */
1203 }
1204 data->flag |= CONSTRAINT_IK_AUTO;
1205 /* Add a temporary auto IK constraint here, as we will only temporarily active this
1206 * target-less bone during transform. (Target-less IK constraints are treated as if they are
1207 * disabled unless they are transformed).
1208 * Only do this for targetless IK though, AutoIK already added a constraint in
1209 * pose_grab_with_ik_add() beforehand. */
1210 if ((data->flag & CONSTRAINT_IK_TEMP) == 0) {
1212 Main *bmain = CTX_data_main(t->context);
1214 }
1215 }
1216
1217 if (pid) {
1218 pid++;
1219 }
1220 }
1221}
1222
1224{
1225 bPoseChannel *pchan = pid->pchan;
1226 copy_v3_v3(pchan->loc, pid->orig.loc);
1227 copy_v3_v3(pchan->scale, pid->orig.scale);
1228 pchan->curve_in_x = pid->orig.curve_in_x;
1229 pchan->curve_out_x = pid->orig.curve_out_x;
1230 pchan->roll1 = pid->orig.roll1;
1231 pchan->roll2 = pid->orig.roll2;
1232
1233 if (pchan->rotmode > 0) {
1234 copy_v3_v3(pchan->eul, pid->orig.eul);
1235 }
1236 else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
1237 copy_v3_v3(pchan->rotAxis, pid->orig.axis_angle);
1238 pchan->rotAngle = pid->orig.axis_angle[3];
1239 }
1240 else {
1241 copy_qt_qt(pchan->quat, pid->orig.quat);
1242 }
1243}
1244
1246{
1247 bPose *pose = tc->poseobj->pose;
1248
1249 if (!(pose->flag & POSE_MIRROR_EDIT)) {
1250 return;
1251 }
1252
1253 for (PoseInitData_Mirror *pid = static_cast<PoseInitData_Mirror *>(tc->custom.type.data);
1254 pid->pchan;
1255 pid++)
1256 {
1258 }
1259}
1260
1261/* Given the transform mode `tmode` return a Vector of RNA paths that were possibly modified during
1262 * that transformation. */
1264 const eTfmMode tmode,
1265 ToolSettings *toolsettings,
1266 const StringRef rotation_path,
1267 const bool targetless_ik,
1268 const bool is_connected,
1269 const bool transforming_more_than_one_bone)
1270{
1271 Vector<RNAPath> rna_paths;
1272
1273 /* Handle the cases where we always need to key location, regardless of
1274 * transform mode. */
1275 if (transforming_more_than_one_bone &&
1277 {
1278 rna_paths.append({"location"});
1279 }
1280 else if (toolsettings->transform_pivot_point == V3D_AROUND_CURSOR) {
1281 rna_paths.append({"location"});
1282 }
1283
1284 /* Handle the transform-mode-specific cases. */
1285 switch (tmode) {
1286 case TFM_TRANSLATION:
1287 /* NOTE: this used to *not* add location if we were doing targetless IK.
1288 * However, that was wrong because of the following situations:
1289 *
1290 * 1. The user can grab the *base* of the bone chain, in which case that
1291 * bone's location does indeed get its location moved, and thus needs
1292 * its location keyed.
1293 * 2. The user can also have bones outside of a bone chain selected, in
1294 * which case they get moved normally, and thus those
1295 * outside-of-a-chain bones need their location keyed.
1296 *
1297 * So for now we're just adding location regardless of targetless IK. This
1298 * unfortunately means that location gets keyed on a lot of bones that
1299 * don't need it when doing targetless ik, but that's better than
1300 * *failing* to key bones that *do* need it. Additionally, case 2 above
1301 * means that outside-of-a-chain bones also get their *rotation*
1302 * unnecessarily keyed when doing targetless IK on another selected chain.
1303 *
1304 * Being precise and only adding location/rotation for the bones that
1305 * really need it when doing targetless IK will require more information
1306 * to be passed to this function.
1307 *
1308 * TODO: get the needed information and make this more precise. */
1309 if (!is_connected) {
1310 rna_paths.append_non_duplicates({"location"});
1311 }
1312 if (targetless_ik) {
1313 rna_paths.append({rotation_path});
1314 }
1315 break;
1316
1317 case TFM_ROTATION:
1318 case TFM_TRACKBALL:
1319 if ((toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
1320 rna_paths.append({rotation_path});
1321 }
1322 break;
1323
1324 case TFM_RESIZE:
1325 if ((toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
1326 rna_paths.append({"scale"});
1327 }
1328 break;
1329
1330 default:
1331 break;
1332 }
1333 return rna_paths;
1334}
1335
1337 Scene *scene,
1338 Object *ob,
1339 short targetless_ik,
1340 const eTfmMode tmode,
1341 const bool transforming_more_than_one_bone)
1342{
1343
1344 bPose *pose = ob->pose;
1345 LISTBASE_FOREACH (bPoseChannel *, pchan, &pose->chanbase) {
1346 if ((pchan->runtime.flag & POSE_RUNTIME_TRANSFORM) == 0 &&
1347 !((pose->flag & POSE_MIRROR_EDIT) && (pchan->bone->flag & BONE_TRANSFORM_MIRROR)))
1348 {
1349 continue;
1350 }
1351
1352 Vector<RNAPath> rna_paths;
1353 const StringRef rotation_path = animrig::get_rotation_mode_path(
1354 eRotationModes(pchan->rotmode));
1355
1357 const bool is_connected = pchan->bone->parent != nullptr &&
1358 (pchan->bone->flag & BONE_CONNECTED);
1360 scene->toolsettings,
1361 rotation_path,
1362 targetless_ik,
1363 is_connected,
1364 transforming_more_than_one_bone);
1365 }
1366 else {
1367 rna_paths = {{"location"}, {rotation_path}, {"scale"}};
1368 }
1369
1370 animrig::autokeyframe_pose_channel(C, scene, ob, pchan, rna_paths.as_span(), targetless_ik);
1371 }
1372}
1373
1375{
1376 if (t->mode == TFM_BONESIZE) {
1377 /* Handle the exception where for TFM_BONESIZE in edit mode we pretend to be
1378 * in pose mode (to use bone orientation matrix),
1379 * in that case we have to do mirroring as well. */
1381 Object *ob = tc->poseobj;
1382 bArmature *arm = static_cast<bArmature *>(ob->data);
1383 if (ob->mode == OB_MODE_EDIT) {
1384 if (arm->flag & ARM_MIRROR_EDIT) {
1385 if (t->state != TRANS_CANCEL) {
1387 }
1388 else {
1389 restoreBones(tc);
1390 }
1391 }
1392 }
1393 else if (ob->mode == OB_MODE_POSE) {
1394 /* Actually support #TFM_BONESIZE in pose-mode as well. */
1396 bPose *pose = ob->pose;
1397 if (arm->flag & ARM_MIRROR_EDIT || pose->flag & POSE_MIRROR_EDIT) {
1399 }
1400 }
1401 }
1402 }
1403 else {
1404 GSet *motionpath_updates = BLI_gset_ptr_new("motionpath updates");
1405
1407 Object *ob = tc->poseobj;
1408 bPose *pose = ob->pose;
1409
1410 if (pose->flag & POSE_MIRROR_EDIT) {
1411 if (t->state != TRANS_CANCEL) {
1413 }
1414 else {
1416 }
1417 }
1418
1419 /* If animtimer is running, and the object already has animation data,
1420 * check if the auto-record feature means that we should record 'samples'
1421 * (i.e. un-editable animation values).
1422 *
1423 * Context is needed for keying set poll() functions.
1424 */
1425
1426 /* TODO: autokeyframe calls need some setting to specify to add samples
1427 * (FPoints) instead of keyframes? */
1428 if ((t->animtimer) && (t->context) && animrig::is_autokey_on(t->scene)) {
1429
1430 /* XXX: this currently doesn't work, since flags aren't set yet! */
1431 int targetless_ik = (t->flag & T_AUTOIK);
1432
1433 animrecord_check_state(t, &ob->id);
1434 autokeyframe_pose(t->context, t->scene, ob, targetless_ik, t->mode, t->data_len_all > 1);
1435 }
1436
1437 if (motionpath_need_update_pose(t->scene, ob)) {
1438 BLI_gset_insert(motionpath_updates, ob);
1439 }
1440
1442 }
1443
1444 /* Update motion paths once for all transformed bones in an object. */
1445 GSetIterator gs_iter;
1446 GSET_ITER (gs_iter, motionpath_updates) {
1447 Object *ob = static_cast<Object *>(BLI_gsetIterator_getKey(&gs_iter));
1449 }
1450 BLI_gset_free(motionpath_updates, nullptr);
1451 }
1452}
1453
1455
1456/* -------------------------------------------------------------------- */
1459
1461 bPoseChannel &pose_bone,
1462 const int mode,
1463 const short around)
1464{
1466 if (&pose_bone == &child) {
1467 return;
1468 }
1469 Bone *bone = child.bone;
1470 if ((bone->flag & BONE_HINGE) && (bone->flag & BONE_CONNECTED)) {
1472 }
1473 else if ((child.runtime.flag & POSE_RUNTIME_TRANSFORM) &&
1475 {
1477 }
1478 else {
1480 }
1481 });
1482}
1483
1484void transform_convert_pose_transflags_update(Object *ob, const int mode, const short around)
1485{
1486 bArmature *arm = static_cast<bArmature *>(ob->data);
1487
1488 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
1489 if (blender::animrig::bone_is_visible(arm, pchan)) {
1490 if (pchan->flag & POSE_SELECTED) {
1491 pchan->runtime.flag |= POSE_RUNTIME_TRANSFORM;
1492 }
1493 else {
1494 pchan->runtime.flag &= ~POSE_RUNTIME_TRANSFORM;
1495 }
1496
1497 pchan->runtime.flag &= ~POSE_RUNTIME_HINGE_CHILD_TRANSFORM;
1498 pchan->runtime.flag &= ~POSE_RUNTIME_TRANSFORM_CHILD;
1499 }
1500 else {
1501 pchan->runtime.flag &= ~POSE_RUNTIME_TRANSFORM;
1502 }
1503 }
1504
1505 /* Make sure no bone can be transformed when a parent is transformed. */
1507 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
1508 if (pchan->runtime.flag & POSE_RUNTIME_TRANSFORM) {
1509 pose_channel_children_clear_transflag(*ob->pose, *pchan, mode, around);
1510 }
1511 }
1512 }
1513}
1514
1516{
1517 bPoseChannel *chanlist[256];
1519 int segcount, apply = 0;
1520
1521 /* Now we got a difficult situation... we have to find the
1522 * target-less IK pchans, and apply transformation to the all
1523 * pchans that were in the chain. */
1524
1525 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
1526 data = has_targetless_ik(pchan);
1527 if (data && (data->flag & CONSTRAINT_IK_AUTO)) {
1528
1529 /* Fill the array with the bones of the chain (`armature.cc` does same, keep it synced). */
1530 segcount = 0;
1531
1532 /* Exclude tip from chain? */
1533 bPoseChannel *parchan = (data->flag & CONSTRAINT_IK_TIP) ? pchan : pchan->parent;
1534
1535 /* Find the chain's root & count the segments needed. */
1536 for (; parchan; parchan = parchan->parent) {
1537 chanlist[segcount] = parchan;
1538 segcount++;
1539
1540 if (segcount == data->rootbone || segcount > 255) {
1541 break; /* 255 is weak. */
1542 }
1543 }
1544 for (; segcount; segcount--) {
1545 float mat[4][4];
1546
1547 /* `pose_mat(b) = pose_mat(b-1) * offs_bone * channel * constraint * IK`. */
1548 /* We put in channel the entire result of: `mat = (channel * constraint * IK)`. */
1549 /* `pose_mat(b) = pose_mat(b-1) * offs_bone * mat`. */
1550 /* `mat = pose_mat(b) * inv(pose_mat(b-1) * offs_bone)`. */
1551
1552 parchan = chanlist[segcount - 1];
1553 /* Ensures it gets an auto key inserted. */
1555
1556 BKE_armature_mat_pose_to_bone(parchan, parchan->pose_mat, mat);
1557 /* Apply and decompose, doesn't work for constraints or non-uniform scale well. */
1558 {
1559 float rmat3[3][3], qrmat[3][3], imat3[3][3], smat[3][3];
1560
1561 copy_m3_m4(rmat3, mat);
1562 /* Make sure that our rotation matrix only contains rotation and not scale. */
1563 normalize_m3(rmat3);
1564
1565 /* Rotation. */
1566 /* #22409 is partially caused by this, as slight numeric error introduced during
1567 * the solving process leads to locked-axis values changing. However, we cannot modify
1568 * the values here, or else there are huge discrepancies between IK-solver (interactive)
1569 * and applied poses. */
1570 BKE_pchan_mat3_to_rot(parchan, rmat3, false);
1571
1572 /* For size, remove rotation. */
1573 /* Causes problems with some constraints (so apply only if needed). */
1574 if (data->flag & CONSTRAINT_IK_STRETCH) {
1575 BKE_pchan_rot_to_mat3(parchan, qrmat);
1576 invert_m3_m3(imat3, qrmat);
1577 mul_m3_m3m3(smat, rmat3, imat3);
1578 mat3_to_size(parchan->scale, smat);
1579 }
1580
1581 /* Causes problems with some constraints (e.g. child-of), so disable this
1582 * as it is IK shouldn't affect location directly. */
1583 // copy_v3_v3(parchan->loc, mat[3]);
1584 }
1585 }
1586
1587 apply = 1;
1588 data->flag &= ~CONSTRAINT_IK_AUTO;
1589 }
1590 }
1591
1592 return apply;
1593}
1594
1596static void pose_grab_with_ik_clear(Main *bmain, Object *ob)
1597{
1599 bConstraint *con, *next;
1600 bool relations_changed = false;
1601
1602 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
1603 /* Clear all temporary lock flags. */
1605
1606 pchan->constflag &= ~(PCHAN_HAS_IK | PCHAN_HAS_NO_TARGET);
1607
1608 /* Remove all temporary IK-constraints added. */
1609 for (con = static_cast<bConstraint *>(pchan->constraints.first); con; con = next) {
1610 next = con->next;
1611 if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
1612 data = static_cast<bKinematicConstraint *>(con->data);
1613 if (data->flag & CONSTRAINT_IK_TEMP) {
1614 relations_changed = true;
1615
1616 /* `iTaSC` needs clear for removed constraints. */
1617 BIK_clear_data(ob->pose);
1618
1619 BLI_remlink(&pchan->constraints, con);
1620 MEM_freeN(con->data);
1621 MEM_freeN(con);
1622 continue;
1623 }
1624 pchan->constflag |= PCHAN_HAS_IK;
1625 if (data->tar == nullptr || (data->tar->type == OB_ARMATURE && data->subtarget[0] == 0)) {
1626 pchan->constflag |= PCHAN_HAS_NO_TARGET;
1627 }
1628 }
1629 }
1630 }
1631
1632 if (relations_changed) {
1633 /* TODO(sergey): Consider doing partial update only. */
1635 }
1636}
1637
1639{
1640 Object *ob;
1641
1642 if (t->mode == TFM_BONESIZE) {
1643 /* Handle the exception where for TFM_BONESIZE in edit mode we pretend to be
1644 * in pose mode (to use bone orientation matrix),
1645 * in that case we don't do operations like auto-keyframing. */
1647 ob = tc->poseobj;
1649 }
1650 }
1651 else {
1652 const bool canceled = (t->state == TRANS_CANCEL);
1653
1654 if (animrig::is_autokey_on(t->scene) && !canceled) {
1656 }
1657
1658 GSet *motionpath_updates = BLI_gset_ptr_new("motionpath updates");
1659
1661 short targetless_ik = 0;
1662
1663 ob = tc->poseobj;
1664
1665 if ((t->flag & T_AUTOIK) && (t->options & CTX_AUTOCONFIRM)) {
1666 /* When running transform non-interactively (operator exec),
1667 * we need to update the pose otherwise no updates get called during
1668 * transform and the auto-IK is not applied. see #26164. */
1669 Object *pose_ob = tc->poseobj;
1670 BKE_pose_where_is(t->depsgraph, t->scene, pose_ob);
1671 }
1672
1673 /* Set POSE_RUNTIME_TRANSFORM flags for auto-key, gizmo draw might have changed them. */
1674 if (!canceled && (t->mode != TFM_DUMMY)) {
1676 }
1677
1678 /* If target-less IK grabbing, we calculate the pchan transforms and clear flag. */
1679 if (!canceled && t->mode == TFM_TRANSLATION) {
1680 targetless_ik = apply_targetless_ik(ob);
1681 }
1682 else {
1683 /* Not forget to clear the auto flag. */
1684 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
1686 if (data) {
1687 data->flag &= ~CONSTRAINT_IK_AUTO;
1688 }
1689 }
1690 }
1691
1692 if (t->mode == TFM_TRANSLATION) {
1693 Main *bmain = CTX_data_main(t->context);
1694 pose_grab_with_ik_clear(bmain, ob);
1695 }
1696
1697 /* Automatic inserting of keys and unkeyed tagging -
1698 * only if transform wasn't canceled (or #TFM_DUMMY). */
1699 if (!canceled && (t->mode != TFM_DUMMY)) {
1700 autokeyframe_pose(C, t->scene, ob, targetless_ik, t->mode, t->data_len_all > 1);
1702 }
1703 else {
1705 }
1706
1707 if (t->mode != TFM_DUMMY && motionpath_need_update_pose(t->scene, ob)) {
1708 BLI_gset_insert(motionpath_updates, ob);
1709 }
1710 }
1711
1712 /* Update motion paths once for all transformed bones in an object. */
1713 GSetIterator gs_iter;
1714 GSET_ITER (gs_iter, motionpath_updates) {
1717 ob = static_cast<Object *>(BLI_gsetIterator_getKey(&gs_iter));
1718 ED_pose_recalculate_paths(C, t->scene, ob, range);
1719 }
1720 BLI_gset_free(motionpath_updates, nullptr);
1721 }
1722}
1723
1725
1727 /*flags*/ (T_EDIT | T_POINTS),
1728 /*create_trans_data*/ createTransArmatureVerts,
1729 /*recalc_data*/ recalcData_edit_armature,
1730 /*special_aftertrans_update*/ nullptr,
1731};
1732
1734 /*flags*/ 0,
1735 /*create_trans_data*/ createTransPose,
1736 /*recalc_data*/ recalcData_pose,
1737 /*special_aftertrans_update*/ special_aftertrans_update__pose,
1738};
1739
1740} // 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.
void BKE_pose_channel_transform_orientation(const bArmature *arm, const bPoseChannel *pose_bone, float r_pose_orientation[3][3])
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
void BKE_pose_channel_transform_location(const bArmature *arm, const bPoseChannel *pose_bone, float r_pose_space_pivot[3])
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])
bArmature * BKE_armature_from_object(Object *ob)
void BKE_pchan_apply_mat4(bPoseChannel *pchan, const float mat[4][4], bool use_compat)
void BKE_pchan_to_mat4(const bPoseChannel *pchan, float r_chanmat[4][4])
void BKE_pose_where_is(Depsgraph *depsgraph, Scene *scene, Object *ob)
void BKE_bone_parent_transform_calc_from_pchan(const bPoseChannel *pchan, BoneParentTransform *r_bpt)
void BKE_pchan_mat3_to_rot(bPoseChannel *pchan, const float mat[3][3], bool use_compat)
void BKE_armature_mat_pose_to_bone(const bPoseChannel *pchan, const float inmat[4][4], float outmat[4][4])
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)
@ RPT_DEBUG
Definition BKE_report.hh:34
@ RPT_ERROR
Definition BKE_report.hh:39
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:153
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#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:1074
@ MOTIONPATH_BAKE_HAS_PATHS
@ POSE_RUNTIME_TRANSFORM
@ POSE_RUNTIME_HINGE_CHILD_TRANSFORM
@ POSE_RUNTIME_TRANSFORM_CHILD
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_SELECTED
@ POSE_TRANSFORM_AROUND_CUSTOM_TX
@ POSE_AUTO_IK
@ POSE_MIRROR_EDIT
@ POSE_MIRROR_RELATIVE
@ BONE_ROOTSEL
@ BONE_SELECTED
@ BONE_EDITMODE_LOCKED
@ BONE_TRANSFORM_MIRROR
@ BONE_NO_LOCAL_LOCATION
@ BONE_TIPSEL
@ BONE_CONNECTED
@ BONE_HINGE
@ 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_ARMATURE
@ OB_LOCK_ROTZ
@ OB_LOCK_ROT
@ OB_LOCK_ROTX
@ OB_LOCK_ROTY
@ OB_LOCK_LOC
@ OB_LOCK_SCALE
@ 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
void pose_bone_descendent_iterator(bPose &pose, bPoseChannel &pose_bone, FunctionRef< void(bPoseChannel &child_bone)> callback)
bool is_autokey_on(const Scene *scene)
bool autokeyframe_cfra_can_key(const Scene *scene, ID *id)
bool bone_is_visible(const bArmature *armature, const Bone *bone)
StringRef get_rotation_mode_path(eRotationModes rotation_mode)
Definition anim_rna.cc:82
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 add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, TransData *td, TransDataExtension *td_ext)
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 pose_channel_children_clear_transflag(bPose &pose, bPoseChannel &pose_bone, const int mode, const short around)
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)
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: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 ToolSettings * toolsettings
ListBase * edbo
struct bConstraint * next
struct Bone * bone
struct bPoseChannel * parent
struct Object * custom
float constinv[4][4]
struct bPoseChannel_Runtime runtime
float pose_mat[4][4]
ListBase chanbase
bAnimVizSettings avs
struct blender::ed::transform::PoseInitData_Mirror::@071300035116026275347300315260062260314050265325 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.