Blender V4.3
armature_utils.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
10#include "DNA_object_types.h"
11
12#include "MEM_guardedalloc.h"
13
14#include "BLI_blenlib.h"
15#include "BLI_math_matrix.h"
16#include "BLI_math_vector.h"
17#include "BLI_string_utils.hh"
18
19#include "BKE_armature.hh"
20#include "BKE_global.hh"
21#include "BKE_idprop.hh"
22#include "BKE_lib_id.hh"
23#include "BKE_main.hh"
24
25#include "DEG_depsgraph.hh"
26
27#include "ED_armature.hh"
28
30
31#include "armature_intern.hh"
32
33#include <cstring>
34
35/* -------------------------------------------------------------------- */
40{
41 LISTBASE_FOREACH (EditBone *, ebo, edbo) {
42 /* if bone is not selectable, we shouldn't alter this setting... */
43 if ((ebo->flag & BONE_UNSELECTABLE) == 0) {
44 if ((ebo->flag & BONE_CONNECTED) && (ebo->parent)) {
45 if (ebo->parent->flag & BONE_TIPSEL) {
46 ebo->flag |= BONE_ROOTSEL;
47 }
48 else {
49 ebo->flag &= ~BONE_ROOTSEL;
50 }
51 }
52
53 if ((ebo->flag & BONE_TIPSEL) && (ebo->flag & BONE_ROOTSEL)) {
54 ebo->flag |= BONE_SELECTED;
55 }
56 else {
57 ebo->flag &= ~BONE_SELECTED;
58 }
59 }
60 }
61}
62
65/* -------------------------------------------------------------------- */
69int bone_looper(Object *ob, Bone *bone, void *data, int (*bone_func)(Object *, Bone *, void *))
70{
71 /* We want to apply the function bone_func to every bone
72 * in an armature -- feed bone_looper the first bone and
73 * a pointer to the bone_func and watch it go! The int count
74 * can be useful for counting bones with a certain property
75 * (e.g. skinnable)
76 */
77 int count = 0;
78
79 if (bone) {
80 /* only do bone_func if the bone is non null */
81 count += bone_func(ob, bone, data);
82
83 /* try to execute bone_func for the first child */
84 count += bone_looper(ob, static_cast<Bone *>(bone->childbase.first), data, bone_func);
85
86 /* try to execute bone_func for the next bone at this
87 * depth of the recursion.
88 */
89 count += bone_looper(ob, bone->next, data, bone_func);
90 }
91
92 return count;
93}
94
97/* -------------------------------------------------------------------- */
101void bone_free(bArmature *arm, EditBone *bone)
102{
103 if (arm->act_edbone == bone) {
104 arm->act_edbone = nullptr;
105 }
106
107 if (bone->prop) {
108 IDP_FreeProperty(bone->prop);
109 }
110
111 /* Clear references from other edit bones. */
112 LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
113 if (ebone->bbone_next == bone) {
114 ebone->bbone_next = nullptr;
115 }
116 if (ebone->bbone_prev == bone) {
117 ebone->bbone_prev = nullptr;
118 }
119 }
120
122 BLI_freelinkN(arm->edbo, bone);
123}
124
125void ED_armature_ebone_remove_ex(bArmature *arm, EditBone *exBone, bool clear_connected)
126{
127 /* Find any bones that refer to this bone */
128 LISTBASE_FOREACH (EditBone *, curBone, arm->edbo) {
129 if (curBone->parent == exBone) {
130 curBone->parent = exBone->parent;
131 if (clear_connected) {
132 curBone->flag &= ~BONE_CONNECTED;
133 }
134 }
135 }
136
137 bone_free(arm, exBone);
138}
139
141{
142 ED_armature_ebone_remove_ex(arm, exBone, true);
143}
144
146{
147 for (ebone_child = ebone_child->parent; ebone_child; ebone_child = ebone_child->parent) {
148 if (ebone_child == ebone_parent) {
149 return true;
150 }
151 }
152 return false;
153}
154
155EditBone *ED_armature_ebone_find_shared_parent(EditBone *ebone_child[], const uint ebone_child_tot)
156{
157#define EBONE_TEMP_UINT(ebone) (*((uint *)(&((ebone)->temp))))
158
159 /* clear all */
160 for (uint i = 0; i < ebone_child_tot; i++) {
161 for (EditBone *ebone_iter = ebone_child[i]; ebone_iter; ebone_iter = ebone_iter->parent) {
162 EBONE_TEMP_UINT(ebone_iter) = 0;
163 }
164 }
165
166 /* accumulate */
167 for (uint i = 0; i < ebone_child_tot; i++) {
168 for (EditBone *ebone_iter = ebone_child[i]->parent; ebone_iter;
169 ebone_iter = ebone_iter->parent)
170 {
171 EBONE_TEMP_UINT(ebone_iter) += 1;
172 }
173 }
174
175 /* only need search the first chain */
176 for (EditBone *ebone_iter = ebone_child[0]->parent; ebone_iter; ebone_iter = ebone_iter->parent)
177 {
178 if (EBONE_TEMP_UINT(ebone_iter) == ebone_child_tot) {
179 return ebone_iter;
180 }
181 }
182
183#undef EBONE_TEMP_UINT
184
185 return nullptr;
186}
187
188void ED_armature_ebone_to_mat3(EditBone *ebone, float r_mat[3][3])
189{
190 float delta[3], roll;
191
192 /* Find the current bone matrix */
193 sub_v3_v3v3(delta, ebone->tail, ebone->head);
194 roll = ebone->roll;
195 if (!normalize_v3(delta)) {
196 /* Use the orientation of the parent bone if any. */
197 const EditBone *ebone_parent = ebone->parent;
198 if (ebone_parent) {
199 sub_v3_v3v3(delta, ebone_parent->tail, ebone_parent->head);
200 normalize_v3(delta);
201 roll = ebone_parent->roll;
202 }
203 }
204
205 vec_roll_to_mat3_normalized(delta, roll, r_mat);
206}
207
208void ED_armature_ebone_to_mat4(EditBone *ebone, float r_mat[4][4])
209{
210 float m3[3][3];
211
212 ED_armature_ebone_to_mat3(ebone, m3);
213
214 copy_m4_m3(r_mat, m3);
215 copy_v3_v3(r_mat[3], ebone->head);
216}
217
218void ED_armature_ebone_from_mat3(EditBone *ebone, const float mat[3][3])
219{
220 float vec[3], roll;
221 const float len = len_v3v3(ebone->head, ebone->tail);
222
223 mat3_to_vec_roll(mat, vec, &roll);
224
225 madd_v3_v3v3fl(ebone->tail, ebone->head, vec, len);
226 ebone->roll = roll;
227}
228
229void ED_armature_ebone_from_mat4(EditBone *ebone, const float mat[4][4])
230{
231 float mat3[3][3];
232
233 copy_m3_m4(mat3, mat);
234 /* We want normalized matrix here, to be consistent with ebone_to_mat. */
235 BLI_ASSERT_UNIT_M3(mat3);
236
237 sub_v3_v3(ebone->tail, ebone->head);
238 copy_v3_v3(ebone->head, mat[3]);
239 add_v3_v3(ebone->tail, mat[3]);
240 ED_armature_ebone_from_mat3(ebone, mat3);
241}
242
243EditBone *ED_armature_ebone_find_name(const ListBase *edbo, const char *name)
244{
245 return static_cast<EditBone *>(BLI_findstring(edbo, name, offsetof(EditBone, name)));
246}
247
250/* -------------------------------------------------------------------- */
255{
256 char name_flip[MAXBONENAME];
257
258 if (ebo == nullptr) {
259 return nullptr;
260 }
261
262 BLI_string_flip_side_name(name_flip, ebo->name, false, sizeof(name_flip));
263
264 if (!STREQ(name_flip, ebo->name)) {
265 return ED_armature_ebone_find_name(edbo, name_flip);
266 }
267
268 return nullptr;
269}
270
271/* ------------------------------------- */
272
274{
276 /* Select mirrored bones */
277 if (arm->flag & ARM_MIRROR_EDIT) {
278 LISTBASE_FOREACH (EditBone *, curBone, arm->edbo) {
279 if (ANIM_bonecoll_is_visible_editbone(arm, curBone)) {
280 if (curBone->flag & flag) {
281 EditBone *ebone_mirr = ED_armature_ebone_get_mirrored(arm->edbo, curBone);
282 if (ebone_mirr) {
283 ebone_mirr->flag |= (curBone->flag & flag);
284 }
285 }
286 }
287 }
288 }
289}
290
295
297{
298 /* always untag */
299 LISTBASE_FOREACH (EditBone *, curBone, arm->edbo) {
300 curBone->flag &= ~BONE_DONE;
301 }
302
303 /* Select mirrored bones */
304 if (arm->flag & ARM_MIRROR_EDIT) {
305 LISTBASE_FOREACH (EditBone *, curBone, arm->edbo) {
306 if (ANIM_bonecoll_is_visible_editbone(arm, curBone)) {
307 if (curBone->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) {
308 EditBone *ebone_mirr = ED_armature_ebone_get_mirrored(arm->edbo, curBone);
309 if (ebone_mirr && (ebone_mirr->flag & BONE_SELECTED) == 0) {
310 ebone_mirr->flag |= BONE_DONE;
311 }
312 }
313 }
314 }
315
316 LISTBASE_FOREACH (EditBone *, curBone, arm->edbo) {
317 if (curBone->flag & BONE_DONE) {
318 EditBone *ebone_mirr = ED_armature_ebone_get_mirrored(arm->edbo, curBone);
319 curBone->flag |= ebone_mirr->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
320 }
321 }
322 }
323}
324
326{
327 LISTBASE_FOREACH (EditBone *, curBone, arm->edbo) {
328 if (curBone->flag & BONE_DONE) {
329 curBone->flag &= ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL | BONE_DONE);
330 }
331 }
332}
333
334/* ------------------------------------- */
335
337{
338 /* TODO: When this function is called by property updates,
339 * canceling the value change will not restore mirrored bone correctly. */
340
341 /* Currently check_select==true when this function is called from a transform operator,
342 * eg. from 3d viewport. */
343
344 /* no layer check, correct mirror is more important */
345 if (!check_select || ebo->flag & (BONE_TIPSEL | BONE_ROOTSEL)) {
346 EditBone *eboflip = ED_armature_ebone_get_mirrored(arm->edbo, ebo);
347 if (eboflip) {
348 /* We assume X-axis flipping for now. */
349
350 /* Always mirror roll, since it can be changed by moving either head or tail. */
351 eboflip->roll = -ebo->roll;
352
353 if (!check_select || ebo->flag & BONE_TIPSEL) {
354 /* Mirror tail properties. */
355
356 eboflip->tail[0] = -ebo->tail[0];
357 eboflip->tail[1] = ebo->tail[1];
358 eboflip->tail[2] = ebo->tail[2];
359 eboflip->rad_tail = ebo->rad_tail;
360 eboflip->curve_out_x = -ebo->curve_out_x;
361 eboflip->curve_out_z = ebo->curve_out_z;
362 copy_v3_v3(eboflip->scale_out, ebo->scale_out);
363 eboflip->ease2 = ebo->ease2;
364 eboflip->roll2 = -ebo->roll2;
365
366 /* Also move connected children, in case children's name aren't mirrored properly. */
367 LISTBASE_FOREACH (EditBone *, children, arm->edbo) {
368 if (children->parent == eboflip && children->flag & BONE_CONNECTED) {
369 copy_v3_v3(children->head, eboflip->tail);
370 children->rad_head = ebo->rad_tail;
371 }
372 }
373 }
374
375 if (!check_select || ebo->flag & BONE_ROOTSEL) {
376 /* Mirror head properties. */
377 eboflip->head[0] = -ebo->head[0];
378 eboflip->head[1] = ebo->head[1];
379 eboflip->head[2] = ebo->head[2];
380 eboflip->rad_head = ebo->rad_head;
381
382 eboflip->curve_in_x = -ebo->curve_in_x;
383 eboflip->curve_in_z = ebo->curve_in_z;
384 copy_v3_v3(eboflip->scale_in, ebo->scale_in);
385 eboflip->ease1 = ebo->ease1;
386 eboflip->roll1 = -ebo->roll1;
387
388 /* Also move connected parent, in case parent's name isn't mirrored properly. */
389 if (eboflip->parent && eboflip->flag & BONE_CONNECTED) {
390 EditBone *parent = eboflip->parent;
391 copy_v3_v3(parent->tail, eboflip->head);
392 parent->rad_tail = ebo->rad_head;
393 }
394 }
395
396 if (!check_select || ebo->flag & BONE_SELECTED) {
397 /* Mirror bone body properties (both head and tail are selected). */
398 /* TODO: These values can also be changed from pose mode,
399 * so only mirroring them in edit mode is not ideal. */
400 eboflip->dist = ebo->dist;
401 eboflip->weight = ebo->weight;
402
403 eboflip->segments = ebo->segments;
404 eboflip->xwidth = ebo->xwidth;
405 eboflip->zwidth = ebo->zwidth;
406 }
407 }
408 }
409}
410
412{
413 bArmature *arm = static_cast<bArmature *>(obedit->data);
414 LISTBASE_FOREACH (EditBone *, ebo, arm->edbo) {
416 }
417}
418
421/* -------------------------------------------------------------------- */
436
437/* converts Bones to EditBone list, used for tools as well */
439 ListBase *bones,
440 EditBone *parent,
441 Bone *actBone)
442{
443 EditBone *eBone;
444 EditBone *eBoneAct = nullptr;
445 EditBone *eBoneTest = nullptr;
446
447 LISTBASE_FOREACH (Bone *, curBone, bones) {
448 eBone = static_cast<EditBone *>(MEM_callocN(sizeof(EditBone), "make_editbone"));
449 eBone->temp.bone = curBone;
450
451 /* Copy relevant data from bone to eBone
452 * Keep selection logic in sync with ED_armature_edit_sync_selection.
453 */
454 eBone->parent = parent;
455 STRNCPY(eBone->name, curBone->name);
456 eBone->flag = curBone->flag;
457 eBone->inherit_scale_mode = curBone->inherit_scale_mode;
458
459 /* fix selection flags */
460 if (eBone->flag & BONE_SELECTED) {
461 /* if the bone is selected the copy its root selection to the parents tip */
462 eBone->flag |= BONE_TIPSEL;
463 if (eBone->parent && (eBone->flag & BONE_CONNECTED)) {
464 eBone->parent->flag |= BONE_TIPSEL;
465 }
466
467 /* For connected bones, take care when changing the selection when we have a
468 * connected parent, this flag is a copy of '(eBone->parent->flag & BONE_TIPSEL)'. */
469 eBone->flag |= BONE_ROOTSEL;
470 }
471 else {
472 /* if the bone is not selected, but connected to its parent
473 * always use the parents tip selection state */
474 if (eBone->parent && (eBone->flag & BONE_CONNECTED)) {
475 eBone->flag &= ~BONE_ROOTSEL;
476 }
477 }
478
479 copy_v3_v3(eBone->head, curBone->arm_head);
480 copy_v3_v3(eBone->tail, curBone->arm_tail);
481 eBone->roll = curBone->arm_roll;
482
483 /* rest of stuff copy */
484 eBone->length = curBone->length;
485 eBone->dist = curBone->dist;
486 eBone->weight = curBone->weight;
487 eBone->xwidth = curBone->xwidth;
488 eBone->zwidth = curBone->zwidth;
489 eBone->rad_head = curBone->rad_head;
490 eBone->rad_tail = curBone->rad_tail;
491 eBone->segments = curBone->segments;
492 eBone->layer = curBone->layer;
493
494 /* Bendy-Bone parameters */
495 eBone->roll1 = curBone->roll1;
496 eBone->roll2 = curBone->roll2;
497 eBone->curve_in_x = curBone->curve_in_x;
498 eBone->curve_in_z = curBone->curve_in_z;
499 eBone->curve_out_x = curBone->curve_out_x;
500 eBone->curve_out_z = curBone->curve_out_z;
501 eBone->ease1 = curBone->ease1;
502 eBone->ease2 = curBone->ease2;
503
504 copy_v3_v3(eBone->scale_in, curBone->scale_in);
505 copy_v3_v3(eBone->scale_out, curBone->scale_out);
506
507 eBone->bbone_prev_type = curBone->bbone_prev_type;
508 eBone->bbone_next_type = curBone->bbone_next_type;
509
510 eBone->bbone_mapping_mode = eBone_BBoneMappingMode(curBone->bbone_mapping_mode);
511 eBone->bbone_flag = curBone->bbone_flag;
512 eBone->bbone_prev_flag = curBone->bbone_prev_flag;
513 eBone->bbone_next_flag = curBone->bbone_next_flag;
514
515 eBone->color = curBone->color;
516 copy_bonecollection_membership(eBone, curBone);
517
518 if (curBone->prop) {
519 eBone->prop = IDP_CopyProperty(curBone->prop);
520 }
521
522 BLI_addtail(edbo, eBone);
523
524 /* Add children if necessary. */
525 if (curBone->childbase.first) {
526 eBoneTest = make_boneList_recursive(edbo, &curBone->childbase, eBone, actBone);
527 if (eBoneTest) {
528 eBoneAct = eBoneTest;
529 }
530 }
531
532 if (curBone == actBone) {
533 eBoneAct = eBone;
534 }
535 }
536
537 return eBoneAct;
538}
539
541{
542 if (link != nullptr) {
543 LISTBASE_FOREACH (EditBone *, ebone, edbo) {
544 if (ebone->temp.bone == link) {
545 return ebone;
546 }
547 }
548 }
549
550 return nullptr;
551}
552
553EditBone *make_boneList(ListBase *edbo, ListBase *bones, Bone *actBone)
554{
555 BLI_assert(!edbo->first && !edbo->last);
556
557 EditBone *active = make_boneList_recursive(edbo, bones, nullptr, actBone);
558
559 LISTBASE_FOREACH (EditBone *, ebone, edbo) {
560 Bone *bone = ebone->temp.bone;
561
562 /* Convert custom B-Bone handle links. */
563 ebone->bbone_prev = find_ebone_link(edbo, bone->bbone_prev);
564 ebone->bbone_next = find_ebone_link(edbo, bone->bbone_next);
565 }
566
567 return active;
568}
569
582static void armature_finalize_restpose(ListBase *bonelist, ListBase *editbonelist)
583{
584 LISTBASE_FOREACH (Bone *, curBone, bonelist) {
585 /* Set bone's local head/tail.
586 * Note that it's important to use final parent's rest-pose (arm_mat) here,
587 * instead of setting those values from edit-bone's matrix (see #46010). */
588 if (curBone->parent) {
589 float parmat_inv[4][4];
590
591 invert_m4_m4(parmat_inv, curBone->parent->arm_mat);
592
593 /* Get the new head and tail */
594 sub_v3_v3v3(curBone->head, curBone->arm_head, curBone->parent->arm_tail);
595 sub_v3_v3v3(curBone->tail, curBone->arm_tail, curBone->parent->arm_tail);
596
597 mul_mat3_m4_v3(parmat_inv, curBone->head);
598 mul_mat3_m4_v3(parmat_inv, curBone->tail);
599 }
600 else {
601 copy_v3_v3(curBone->head, curBone->arm_head);
602 copy_v3_v3(curBone->tail, curBone->arm_tail);
603 }
604
605 /* Set local matrix and arm_mat (rest-pose).
606 * Do not recurse into children here, armature_finalize_restpose() is already recursive. */
607 BKE_armature_where_is_bone(curBone, curBone->parent, false);
608
609 /* Find the associated editbone */
610 LISTBASE_FOREACH (EditBone *, ebone, editbonelist) {
611 if (ebone->temp.bone == curBone) {
612 float premat[3][3];
613 float postmat[3][3];
614 float difmat[3][3];
615 float imat[3][3];
616
617 /* Get the ebone premat and its inverse. */
618 ED_armature_ebone_to_mat3(ebone, premat);
619 invert_m3_m3(imat, premat);
620
621 /* Get the bone postmat. */
622 copy_m3_m4(postmat, curBone->arm_mat);
623
624 mul_m3_m3m3(difmat, imat, postmat);
625
626#if 0
627 printf("Bone %s\n", curBone->name);
628 print_m4("premat", premat);
629 print_m4("postmat", postmat);
630 print_m4("difmat", difmat);
631 printf("Roll = %f\n", RAD2DEGF(-atan2(difmat[2][0], difmat[2][2])));
632#endif
633
634 curBone->roll = -atan2f(difmat[2][0], difmat[2][2]);
635
636 /* And set rest-position again. */
637 BKE_armature_where_is_bone(curBone, curBone->parent, false);
638 break;
639 }
640 }
641
642 /* Recurse into children... */
643 armature_finalize_restpose(&curBone->childbase, editbonelist);
644 }
645}
646
648{
649 EditBone *eBone, *neBone;
650 Bone *newBone;
651 Object *obt;
652
653 /* armature bones */
656 arm->act_bone = nullptr;
657
658 /* Remove zero sized bones, this gives unstable rest-poses. */
659 for (eBone = static_cast<EditBone *>(arm->edbo->first); eBone; eBone = neBone) {
660 float len_sq = len_squared_v3v3(eBone->head, eBone->tail);
661 neBone = eBone->next;
662 /* TODO(sergey): How to ensure this is a `constexpr`? */
663 if (len_sq <= square_f(0.000001f)) { /* FLT_EPSILON is too large? */
664 /* Find any bones that refer to this bone */
665 LISTBASE_FOREACH (EditBone *, fBone, arm->edbo) {
666 if (fBone->parent == eBone) {
667 fBone->parent = eBone->parent;
668 }
669 }
670 if (G.debug & G_DEBUG) {
671 printf("Warning: removed zero sized bone: %s\n", eBone->name);
672 }
673 bone_free(arm, eBone);
674 }
675 }
676
677 /* Copy the bones from the edit-data into the armature. */
678 LISTBASE_FOREACH (EditBone *, eBone, arm->edbo) {
679 newBone = static_cast<Bone *>(MEM_callocN(sizeof(Bone), "bone"));
680 eBone->temp.bone = newBone; /* Associate the real Bones with the EditBones */
681
682 STRNCPY(newBone->name, eBone->name);
683 copy_v3_v3(newBone->arm_head, eBone->head);
684 copy_v3_v3(newBone->arm_tail, eBone->tail);
685 newBone->arm_roll = eBone->roll;
686
687 newBone->flag = eBone->flag;
688 newBone->inherit_scale_mode = eBone->inherit_scale_mode;
689
690 if (eBone == arm->act_edbone) {
691 /* Don't change active selection, this messes up separate which uses
692 * edit-mode toggle and can separate active bone which is de-selected originally. */
693
694 /* important, edit-bones can be active with only 1 point selected */
695 /* `newBone->flag |= BONE_SELECTED;` */
696 arm->act_bone = newBone;
697 }
698 newBone->roll = 0.0f;
699
700 newBone->weight = eBone->weight;
701 newBone->dist = eBone->dist;
702
703 newBone->xwidth = eBone->xwidth;
704 newBone->zwidth = eBone->zwidth;
705 newBone->rad_head = eBone->rad_head;
706 newBone->rad_tail = eBone->rad_tail;
707 newBone->segments = eBone->segments;
708 newBone->layer = eBone->layer;
709
710 /* Bendy-Bone parameters */
711 newBone->roll1 = eBone->roll1;
712 newBone->roll2 = eBone->roll2;
713 newBone->curve_in_x = eBone->curve_in_x;
714 newBone->curve_in_z = eBone->curve_in_z;
715 newBone->curve_out_x = eBone->curve_out_x;
716 newBone->curve_out_z = eBone->curve_out_z;
717 newBone->ease1 = eBone->ease1;
718 newBone->ease2 = eBone->ease2;
719 copy_v3_v3(newBone->scale_in, eBone->scale_in);
720 copy_v3_v3(newBone->scale_out, eBone->scale_out);
721
722 newBone->bbone_prev_type = eBone->bbone_prev_type;
723 newBone->bbone_next_type = eBone->bbone_next_type;
724
725 newBone->bbone_mapping_mode = eBone->bbone_mapping_mode;
726 newBone->bbone_flag = eBone->bbone_flag;
727 newBone->bbone_prev_flag = eBone->bbone_prev_flag;
728 newBone->bbone_next_flag = eBone->bbone_next_flag;
729
730 newBone->color = eBone->color;
731
733 BoneCollectionReference *newBoneRef = MEM_cnew<BoneCollectionReference>(
734 "ED_armature_from_edit", *ref);
735 BLI_addtail(&newBone->runtime.collections, newBoneRef);
736 }
737
738 if (eBone->prop) {
739 newBone->prop = IDP_CopyProperty(eBone->prop);
740 }
741 }
742
743 /* Fix parenting in a separate pass to ensure ebone->bone connections are valid at this point.
744 * Do not set bone->head/tail here anymore,
745 * using EditBone data for that is not OK since our later fiddling with parent's arm_mat
746 * (for roll conversion) may have some small but visible impact on locations (#46010). */
747 LISTBASE_FOREACH (EditBone *, eBone, arm->edbo) {
748 newBone = eBone->temp.bone;
749 if (eBone->parent) {
750 newBone->parent = eBone->parent->temp.bone;
751 BLI_addtail(&newBone->parent->childbase, newBone);
752 }
753 /* ...otherwise add this bone to the armature's bonebase */
754 else {
755 BLI_addtail(&arm->bonebase, newBone);
756 }
757
758 /* Also transfer B-Bone custom handles. */
759 if (eBone->bbone_prev) {
760 newBone->bbone_prev = eBone->bbone_prev->temp.bone;
761 }
762 if (eBone->bbone_next) {
763 newBone->bbone_next = eBone->bbone_next->temp.bone;
764 }
765 }
766
767 /* Finalize definition of rest-pose data (roll, bone_mat, arm_mat, head/tail...). */
770
772
773 /* so all users of this armature should get rebuilt */
774 for (obt = static_cast<Object *>(bmain->objects.first); obt;
775 obt = static_cast<Object *>(obt->id.next))
776 {
777 if (obt->data == arm) {
778 BKE_pose_rebuild(bmain, obt, arm, true);
779 }
780 }
781
782 DEG_id_tag_update(&arm->id, 0);
783}
784
786{
787 /* Clear the edit-bones list. */
788 if (arm->edbo) {
789 if (arm->edbo->first) {
790 LISTBASE_FOREACH (EditBone *, eBone, arm->edbo) {
791 if (eBone->prop) {
792 IDP_FreeProperty(eBone->prop);
793 }
794 BLI_freelistN(&eBone->bone_collections);
795 }
796
797 BLI_freelistN(arm->edbo);
798 }
799 MEM_freeN(arm->edbo);
800 arm->edbo = nullptr;
801 arm->act_edbone = nullptr;
802 }
803}
804
806{
808 arm->edbo = static_cast<ListBase *>(MEM_callocN(sizeof(ListBase), "edbo armature"));
809 arm->act_edbone = make_boneList(arm->edbo, &arm->bonebase, arm->act_bone);
810}
811
814/* -------------------------------------------------------------------- */
818void ED_armature_ebone_listbase_free(ListBase *lb, const bool do_id_user)
819{
820 EditBone *ebone, *ebone_next;
821
822 for (ebone = static_cast<EditBone *>(lb->first); ebone; ebone = ebone_next) {
823 ebone_next = ebone->next;
824
825 if (ebone->prop) {
826 IDP_FreeProperty_ex(ebone->prop, do_id_user);
827 }
828
830
831 MEM_freeN(ebone);
832 }
833
835}
836
837void ED_armature_ebone_listbase_copy(ListBase *lb_dst, ListBase *lb_src, const bool do_id_user)
838{
840
841 LISTBASE_FOREACH (EditBone *, ebone_src, lb_src) {
842 EditBone *ebone_dst = static_cast<EditBone *>(MEM_dupallocN(ebone_src));
843 if (ebone_dst->prop) {
844 ebone_dst->prop = IDP_CopyProperty_ex(ebone_dst->prop,
845 do_id_user ? 0 : LIB_ID_CREATE_NO_USER_REFCOUNT);
846 }
847 ebone_src->temp.ebone = ebone_dst;
848 BLI_addtail(lb_dst, ebone_dst);
849 }
850
851 /* set pointers */
852 LISTBASE_FOREACH (EditBone *, ebone_dst, lb_dst) {
853 if (ebone_dst->parent) {
854 ebone_dst->parent = ebone_dst->parent->temp.ebone;
855 }
856 if (ebone_dst->bbone_next) {
857 ebone_dst->bbone_next = ebone_dst->bbone_next->temp.ebone;
858 }
859 if (ebone_dst->bbone_prev) {
860 ebone_dst->bbone_prev = ebone_dst->bbone_prev->temp.ebone;
861 }
862
863 BLI_duplicatelist(&ebone_dst->bone_collections, &ebone_dst->bone_collections);
864 }
865}
866
868{
869 /* be sure they don't hang ever */
870 LISTBASE_FOREACH (EditBone *, ebone, lb) {
871 ebone->temp.p = nullptr;
872 }
873}
874
877/* -------------------------------------------------------------------- */
885{
886 if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
887 return ((ebone->flag & (BONE_SELECTED | BONE_TIPSEL)) |
888 ((ebone->parent->flag & BONE_TIPSEL) ? BONE_ROOTSEL : 0));
889 }
890 return (ebone->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL));
891}
892
894{
896
897 if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
899 ebone->parent->flag &= ~BONE_TIPSEL;
900
901 ebone->flag |= flag;
902 ebone->parent->flag |= (flag & BONE_ROOTSEL) ? BONE_TIPSEL : 0;
903 }
904 else {
906 ebone->flag |= flag;
907 }
908}
909
915
921
923{
924 /* NOTE: this function could be used in more places. */
925
926 int flag;
927 if (select) {
928 BLI_assert((ebone->flag & BONE_UNSELECTABLE) == 0);
930 }
931 else {
932 flag = 0;
933 }
935}
936
C++ functions to deal with Armature collections (i.e. the successor of bone layers).
bool ANIM_bonecoll_is_visible_editbone(const bArmature *armature, const EditBone *ebone)
void ANIM_armature_bonecoll_reconstruct(bArmature *armature)
void BKE_armature_bone_hash_make(bArmature *arm)
Definition armature.cc:814
void BKE_pose_rebuild(Main *bmain, Object *ob, bArmature *arm, bool do_id_user)
Definition armature.cc:2767
void BKE_armature_bonelist_free(ListBase *lb, bool do_id_user)
Definition armature.cc:540
void BKE_armature_where_is_bone(Bone *bone, const Bone *bone_parent, bool use_recursion)
Definition armature.cc:2625
void mat3_to_vec_roll(const float mat[3][3], float r_vec[3], float *r_roll)
Definition armature.cc:2456
void BKE_armature_bone_hash_free(bArmature *arm)
Definition armature.cc:821
void vec_roll_to_mat3_normalized(const float nor[3], float roll, float r_mat[3][3])
Definition armature.cc:2482
@ G_DEBUG
void IDP_FreeProperty(IDProperty *prop)
Definition idprop.cc:1227
IDProperty * IDP_CopyProperty_ex(const IDProperty *prop, int flag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:843
IDProperty * IDP_CopyProperty(const IDProperty *prop) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:861
void IDP_FreeProperty_ex(IDProperty *prop, bool do_id_user)
Definition idprop.cc:1221
@ LIB_ID_CREATE_NO_USER_REFCOUNT
#define BLI_assert(a)
Definition BLI_assert.h:50
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
void * BLI_findstring(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define LISTBASE_FOREACH(type, var, list)
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:269
void void void void void void BLI_duplicatelist(struct ListBase *dst, const struct ListBase *src) ATTR_NONNULL(1
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:496
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
#define BLI_ASSERT_UNIT_M3(m)
MINLINE float square_f(float a)
void copy_m3_m4(float m1[3][3], const float m2[4][4])
bool invert_m3_m3(float inverse[3][3], const float mat[3][3])
void copy_m4_m3(float m1[4][4], const float m2[3][3])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
void print_m4(const char *str, const float m[4][4])
void mul_mat3_m4_v3(const float mat[4][4], float r[3])
#define RAD2DEGF(_rad)
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE float len_squared_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 void madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], float f)
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float normalize_v3(float n[3])
#define STRNCPY(dst, src)
Definition BLI_string.h:593
size_t BLI_string_flip_side_name(char *name_dst, const char *name_src, bool strip_number, size_t name_dst_maxncpy) ATTR_NONNULL(1
unsigned int uint
#define STREQ(a, b)
void DEG_id_tag_update(ID *id, unsigned int flags)
#define MAXBONENAME
eBone_BBoneMappingMode
@ BONE_ROOTSEL
@ BONE_SELECTED
@ BONE_UNSELECTABLE
@ BONE_DONE
@ BONE_TIPSEL
@ BONE_CONNECTED
@ ARM_MIRROR_EDIT
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
bool ED_armature_ebone_is_child_recursive(EditBone *ebone_parent, EditBone *ebone_child)
void ED_armature_ebone_selectflag_disable(EditBone *ebone, int flag)
void ED_armature_edit_transform_mirror_update(Object *obedit)
void ED_armature_ebone_transform_mirror_update(bArmature *arm, EditBone *ebo, bool check_select)
static EditBone * make_boneList_recursive(ListBase *edbo, ListBase *bones, EditBone *parent, Bone *actBone)
EditBone * ED_armature_ebone_find_name(const ListBase *edbo, const char *name)
void armature_tag_select_mirrored(bArmature *arm)
int bone_looper(Object *ob, Bone *bone, void *data, int(*bone_func)(Object *, Bone *, void *))
void ED_armature_ebone_listbase_temp_clear(ListBase *lb)
void ED_armature_ebone_from_mat3(EditBone *ebone, const float mat[3][3])
void ED_armature_ebone_to_mat4(EditBone *ebone, float r_mat[4][4])
void ED_armature_ebone_remove_ex(bArmature *arm, EditBone *exBone, bool clear_connected)
void ED_armature_edit_sync_selection(ListBase *edbo)
int ED_armature_ebone_selectflag_get(const EditBone *ebone)
void ED_armature_ebone_selectflag_set(EditBone *ebone, int flag)
void armature_select_mirrored_ex(bArmature *arm, const int flag)
void ED_armature_ebone_select_set(EditBone *ebone, bool select)
void ED_armature_edit_free(bArmature *arm)
static void copy_bonecollection_membership(EditBone *eBone, const Bone *bone)
void ED_armature_ebone_listbase_free(ListBase *lb, const bool do_id_user)
static void armature_finalize_restpose(ListBase *bonelist, ListBase *editbonelist)
void armature_select_mirrored(bArmature *arm)
EditBone * ED_armature_ebone_find_shared_parent(EditBone *ebone_child[], const uint ebone_child_tot)
void ED_armature_ebone_to_mat3(EditBone *ebone, float r_mat[3][3])
void ED_armature_ebone_listbase_copy(ListBase *lb_dst, ListBase *lb_src, const bool do_id_user)
void ED_armature_from_edit(Main *bmain, bArmature *arm)
void ED_armature_ebone_selectflag_enable(EditBone *ebone, int flag)
void armature_tag_unselect(bArmature *arm)
void ED_armature_ebone_remove(bArmature *arm, EditBone *exBone)
void ED_armature_ebone_from_mat4(EditBone *ebone, const float mat[4][4])
#define EBONE_TEMP_UINT(ebone)
EditBone * make_boneList(ListBase *edbo, ListBase *bones, Bone *actBone)
void bone_free(bArmature *arm, EditBone *bone)
void ED_armature_to_edit(bArmature *arm)
static EditBone * find_ebone_link(ListBase *edbo, Bone *link)
EditBone * ED_armature_ebone_get_mirrored(const ListBase *edbo, EditBone *ebo)
#define printf
#define atan2f(x, y)
#define offsetof(t, d)
int len
int count
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
void *(* MEM_dupallocN)(const void *vmemh)
Definition mallocn.cc:39
ccl_device_inline float4 select(const int4 mask, const float4 a, const float4 b)
#define G(x, y, z)
float curve_in_z
BoneColor color
short bbone_next_flag
short bbone_prev_flag
Bone_Runtime runtime
struct Bone * parent
struct Bone * bbone_prev
float arm_head[3]
char name[64]
float arm_tail[3]
struct Bone * bbone_next
char inherit_scale_mode
char bbone_prev_type
float curve_in_x
float scale_out[3]
IDProperty * prop
float curve_out_z
char bbone_mapping_mode
float scale_in[3]
char bbone_next_type
struct Bone * next
float curve_out_x
ListBase childbase
float arm_roll
float curve_out_z
float scale_in[3]
char name[64]
short bbone_prev_flag
float ease2
float weight
float roll1
::BoneColor color
short segments
float tail[3]
IDProperty * prop
char bbone_prev_type
EditBone * parent
float roll2
ListBase bone_collections
float curve_in_x
float zwidth
short bbone_next_flag
float curve_in_z
float length
Bone * bone
float xwidth
EditBone * next
EditBone * bbone_prev
char bbone_next_type
union EditBone::@4 temp
float rad_tail
EditBone * bbone_next
float ease1
eBone_BBoneMappingMode bbone_mapping_mode
float rad_head
float scale_out[3]
char inherit_scale_mode
float curve_out_x
float head[3]
void * next
Definition DNA_ID.h:416
void * last
void * first
ListBase objects
Definition BKE_main.hh:212
struct EditBone * act_edbone
ListBase * edbo
uint8_t flag
Definition wm_window.cc:138