Blender V5.0
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
8
10#include "DNA_object_types.h"
11
12#include "MEM_guardedalloc.h"
13
14#include "BLI_listbase.h"
15#include "BLI_math_matrix.h"
16#include "BLI_math_vector.h"
17#include "BLI_string_utf8.h"
18#include "BLI_string_utils.hh"
19
20#include "BKE_armature.hh"
21#include "BKE_global.hh"
22#include "BKE_idprop.hh"
23#include "BKE_lib_id.hh"
24#include "BKE_main.hh"
25
26#include "DEG_depsgraph.hh"
27
28#include "ED_armature.hh"
29
30#include "ANIM_armature.hh"
32
33#include "armature_intern.hh"
34
35#include <cstring>
36
37/* -------------------------------------------------------------------- */
40
42{
43 LISTBASE_FOREACH (EditBone *, ebo, edbo) {
44 /* if bone is not selectable, we shouldn't alter this setting... */
45 if ((ebo->flag & BONE_UNSELECTABLE) == 0) {
46 if ((ebo->flag & BONE_CONNECTED) && (ebo->parent)) {
47 if (ebo->parent->flag & BONE_TIPSEL) {
48 ebo->flag |= BONE_ROOTSEL;
49 }
50 else {
51 ebo->flag &= ~BONE_ROOTSEL;
52 }
53 }
54
55 if ((ebo->flag & BONE_TIPSEL) && (ebo->flag & BONE_ROOTSEL)) {
56 ebo->flag |= BONE_SELECTED;
57 }
58 else {
59 ebo->flag &= ~BONE_SELECTED;
60 }
61 }
62 }
63}
64
66
67/* -------------------------------------------------------------------- */
70
71int bone_looper(Object *ob, Bone *bone, void *data, int (*bone_func)(Object *, Bone *, void *))
72{
73 /* We want to apply the function bone_func to every bone
74 * in an armature -- feed bone_looper the first bone and
75 * a pointer to the bone_func and watch it go! The int count
76 * can be useful for counting bones with a certain property
77 * (e.g. skinnable)
78 */
79 int count = 0;
80
81 if (bone) {
82 /* only do bone_func if the bone is non null */
83 count += bone_func(ob, bone, data);
84
85 /* try to execute bone_func for the first child */
86 count += bone_looper(ob, static_cast<Bone *>(bone->childbase.first), data, bone_func);
87
88 /* try to execute bone_func for the next bone at this
89 * depth of the recursion.
90 */
91 count += bone_looper(ob, bone->next, data, bone_func);
92 }
93
94 return count;
95}
96
98
99/* -------------------------------------------------------------------- */
102
103void bone_free(bArmature *arm, EditBone *bone)
104{
105 if (arm->act_edbone == bone) {
106 arm->act_edbone = nullptr;
107 }
108
109 if (bone->prop) {
110 IDP_FreeProperty(bone->prop);
111 }
112 if (bone->system_properties) {
114 }
115
116 /* Clear references from other edit bones. */
117 LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
118 if (ebone->bbone_next == bone) {
119 ebone->bbone_next = nullptr;
120 }
121 if (ebone->bbone_prev == bone) {
122 ebone->bbone_prev = nullptr;
123 }
124 }
125
127 BLI_freelinkN(arm->edbo, bone);
128}
129
130void ED_armature_ebone_remove_ex(bArmature *arm, EditBone *exBone, bool clear_connected)
131{
132 /* Find any bones that refer to this bone */
133 LISTBASE_FOREACH (EditBone *, curBone, arm->edbo) {
134 if (curBone->parent == exBone) {
135 curBone->parent = exBone->parent;
136 if (clear_connected) {
137 curBone->flag &= ~BONE_CONNECTED;
138 }
139 }
140 }
141
142 bone_free(arm, exBone);
143}
144
146{
147 ED_armature_ebone_remove_ex(arm, exBone, true);
148}
149
151{
152 for (ebone_child = ebone_child->parent; ebone_child; ebone_child = ebone_child->parent) {
153 if (ebone_child == ebone_parent) {
154 return true;
155 }
156 }
157 return false;
158}
159
160EditBone *ED_armature_ebone_find_shared_parent(EditBone *ebone_child[], const uint ebone_child_tot)
161{
162#define EBONE_TEMP_UINT(ebone) (*((uint *)(&((ebone)->temp))))
163
164 /* clear all */
165 for (uint i = 0; i < ebone_child_tot; i++) {
166 for (EditBone *ebone_iter = ebone_child[i]; ebone_iter; ebone_iter = ebone_iter->parent) {
167 EBONE_TEMP_UINT(ebone_iter) = 0;
168 }
169 }
170
171 /* accumulate */
172 for (uint i = 0; i < ebone_child_tot; i++) {
173 for (EditBone *ebone_iter = ebone_child[i]->parent; ebone_iter;
174 ebone_iter = ebone_iter->parent)
175 {
176 EBONE_TEMP_UINT(ebone_iter) += 1;
177 }
178 }
179
180 /* only need search the first chain */
181 for (EditBone *ebone_iter = ebone_child[0]->parent; ebone_iter; ebone_iter = ebone_iter->parent)
182 {
183 if (EBONE_TEMP_UINT(ebone_iter) == ebone_child_tot) {
184 return ebone_iter;
185 }
186 }
187
188#undef EBONE_TEMP_UINT
189
190 return nullptr;
191}
192
193void ED_armature_ebone_to_mat3(EditBone *ebone, float r_mat[3][3])
194{
195 float delta[3], roll;
196
197 /* Find the current bone matrix */
198 sub_v3_v3v3(delta, ebone->tail, ebone->head);
199 roll = ebone->roll;
200 if (!normalize_v3(delta)) {
201 /* Use the orientation of the parent bone if any. */
202 const EditBone *ebone_parent = ebone->parent;
203 if (ebone_parent) {
204 sub_v3_v3v3(delta, ebone_parent->tail, ebone_parent->head);
205 normalize_v3(delta);
206 roll = ebone_parent->roll;
207 }
208 }
209
210 vec_roll_to_mat3_normalized(delta, roll, r_mat);
211}
212
213void ED_armature_ebone_to_mat4(EditBone *ebone, float r_mat[4][4])
214{
215 float m3[3][3];
216
217 ED_armature_ebone_to_mat3(ebone, m3);
218
219 copy_m4_m3(r_mat, m3);
220 copy_v3_v3(r_mat[3], ebone->head);
221}
222
223void ED_armature_ebone_from_mat3(EditBone *ebone, const float mat[3][3])
224{
225 float vec[3], roll;
226 const float len = len_v3v3(ebone->head, ebone->tail);
227
228 mat3_to_vec_roll(mat, vec, &roll);
229
230 madd_v3_v3v3fl(ebone->tail, ebone->head, vec, len);
231 ebone->roll = roll;
232}
233
234void ED_armature_ebone_from_mat4(EditBone *ebone, const float mat[4][4])
235{
236 float mat3[3][3];
237
238 copy_m3_m4(mat3, mat);
239 /* We want normalized matrix here, to be consistent with ebone_to_mat. */
240 BLI_ASSERT_UNIT_M3(mat3);
241
242 sub_v3_v3(ebone->tail, ebone->head);
243 copy_v3_v3(ebone->head, mat[3]);
244 add_v3_v3(ebone->tail, mat[3]);
245 ED_armature_ebone_from_mat3(ebone, mat3);
246}
247
249{
250 return static_cast<EditBone *>(BLI_findstring(edbo, name, offsetof(EditBone, name)));
251}
252
254
255/* -------------------------------------------------------------------- */
258
260{
261 char name_flip[MAXBONENAME];
262
263 if (ebo == nullptr) {
264 return nullptr;
265 }
266
267 BLI_string_flip_side_name(name_flip, ebo->name, false, sizeof(name_flip));
268
269 if (!STREQ(name_flip, ebo->name)) {
270 return ED_armature_ebone_find_name(edbo, name_flip);
271 }
272
273 return nullptr;
274}
275
276/* ------------------------------------- */
277
279{
281 /* Select mirrored bones */
282 if (arm->flag & ARM_MIRROR_EDIT) {
283 LISTBASE_FOREACH (EditBone *, curBone, arm->edbo) {
284 if (blender::animrig::bone_is_visible(arm, curBone)) {
285 if (curBone->flag & flag) {
286 EditBone *ebone_mirr = ED_armature_ebone_get_mirrored(arm->edbo, curBone);
287 if (ebone_mirr) {
288 ebone_mirr->flag |= (curBone->flag & flag);
289 }
290 }
291 }
292 }
293 }
294}
295
300
302{
303 /* always untag */
304 LISTBASE_FOREACH (EditBone *, curBone, arm->edbo) {
305 curBone->flag &= ~BONE_DONE;
306 }
307
308 /* Select mirrored bones */
309 if (arm->flag & ARM_MIRROR_EDIT) {
310 LISTBASE_FOREACH (EditBone *, curBone, arm->edbo) {
311 if (blender::animrig::bone_is_visible(arm, curBone)) {
312 if (curBone->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) {
313 EditBone *ebone_mirr = ED_armature_ebone_get_mirrored(arm->edbo, curBone);
314 if (ebone_mirr && (ebone_mirr->flag & BONE_SELECTED) == 0) {
315 ebone_mirr->flag |= BONE_DONE;
316 }
317 }
318 }
319 }
320
321 LISTBASE_FOREACH (EditBone *, curBone, arm->edbo) {
322 if (curBone->flag & BONE_DONE) {
323 EditBone *ebone_mirr = ED_armature_ebone_get_mirrored(arm->edbo, curBone);
324 curBone->flag |= ebone_mirr->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
325 }
326 }
327 }
328}
329
331{
332 LISTBASE_FOREACH (EditBone *, curBone, arm->edbo) {
333 if (curBone->flag & BONE_DONE) {
334 curBone->flag &= ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL | BONE_DONE);
335 }
336 }
337}
338
339/* ------------------------------------- */
340
342{
343 /* TODO: When this function is called by property updates,
344 * canceling the value change will not restore mirrored bone correctly. */
345
346 /* Currently check_select==true when this function is called from a transform operator,
347 * eg. from 3d viewport. */
348
349 /* no layer check, correct mirror is more important */
350 if (!check_select ||
352 {
353 EditBone *eboflip = ED_armature_ebone_get_mirrored(arm->edbo, ebo);
354 if (eboflip) {
355 /* We assume X-axis flipping for now. */
356
357 /* Always mirror roll, since it can be changed by moving either head or tail. */
358 eboflip->roll = -ebo->roll;
359
360 if (!check_select || ebo->flag & BONE_TIPSEL) {
361 /* Mirror tail properties. */
362
363 eboflip->tail[0] = -ebo->tail[0];
364 eboflip->tail[1] = ebo->tail[1];
365 eboflip->tail[2] = ebo->tail[2];
366 eboflip->rad_tail = ebo->rad_tail;
367 eboflip->curve_out_x = -ebo->curve_out_x;
368 eboflip->curve_out_z = ebo->curve_out_z;
369 copy_v3_v3(eboflip->scale_out, ebo->scale_out);
370 eboflip->ease2 = ebo->ease2;
371 eboflip->roll2 = -ebo->roll2;
372
373 /* Also move connected children, in case children's name aren't mirrored properly. */
374 LISTBASE_FOREACH (EditBone *, children, arm->edbo) {
375 if (children->parent == eboflip && children->flag & BONE_CONNECTED) {
376 copy_v3_v3(children->head, eboflip->tail);
377 children->rad_head = ebo->rad_tail;
378 }
379 }
380 }
381
382 if (!check_select || ebo->flag & BONE_ROOTSEL) {
383 /* Mirror head properties. */
384 eboflip->head[0] = -ebo->head[0];
385 eboflip->head[1] = ebo->head[1];
386 eboflip->head[2] = ebo->head[2];
387 eboflip->rad_head = ebo->rad_head;
388
389 eboflip->curve_in_x = -ebo->curve_in_x;
390 eboflip->curve_in_z = ebo->curve_in_z;
391 copy_v3_v3(eboflip->scale_in, ebo->scale_in);
392 eboflip->ease1 = ebo->ease1;
393 eboflip->roll1 = -ebo->roll1;
394
395 /* Also move connected parent, in case parent's name isn't mirrored properly. */
396 if (eboflip->parent && eboflip->flag & BONE_CONNECTED) {
397 EditBone *parent = eboflip->parent;
398 copy_v3_v3(parent->tail, eboflip->head);
399 parent->rad_tail = ebo->rad_head;
400 }
401 }
402
403 if (!check_select || ebo->flag & BONE_SELECTED) {
404 /* Mirror bone body properties (both head and tail are selected). */
405 /* TODO: These values can also be changed from pose mode,
406 * so only mirroring them in edit mode is not ideal. */
407 eboflip->dist = ebo->dist;
408 eboflip->weight = ebo->weight;
409
410 eboflip->segments = ebo->segments;
411 eboflip->xwidth = ebo->xwidth;
412 eboflip->zwidth = ebo->zwidth;
413 }
414 }
415 }
416}
417
419{
420 bArmature *arm = static_cast<bArmature *>(obedit->data);
421 LISTBASE_FOREACH (EditBone *, ebo, arm->edbo) {
423 }
424}
425
427
428/* -------------------------------------------------------------------- */
431
443
444/* converts Bones to EditBone list, used for tools as well */
446 ListBase *bones,
447 EditBone *parent,
448 Bone *actBone)
449{
450 EditBone *eBone;
451 EditBone *eBoneAct = nullptr;
452 EditBone *eBoneTest = nullptr;
453
454 LISTBASE_FOREACH (Bone *, curBone, bones) {
455 eBone = MEM_callocN<EditBone>("make_editbone");
456 eBone->temp.bone = curBone;
457
458 /* Copy relevant data from bone to eBone
459 * Keep selection logic in sync with ED_armature_edit_sync_selection.
460 */
461 eBone->parent = parent;
462 STRNCPY_UTF8(eBone->name, curBone->name);
463 eBone->flag = curBone->flag;
464 eBone->inherit_scale_mode = curBone->inherit_scale_mode;
465 eBone->drawtype = curBone->drawtype;
466
467 /* fix selection flags */
468 if (eBone->flag & BONE_SELECTED) {
469 /* if the bone is selected the copy its root selection to the parents tip */
470 eBone->flag |= BONE_TIPSEL;
471 if (eBone->parent && (eBone->flag & BONE_CONNECTED)) {
472 eBone->parent->flag |= BONE_TIPSEL;
473 }
474
475 /* For connected bones, take care when changing the selection when we have a
476 * connected parent, this flag is a copy of '(eBone->parent->flag & BONE_TIPSEL)'. */
477 eBone->flag |= BONE_ROOTSEL;
478 }
479 else {
480 /* if the bone is not selected, but connected to its parent
481 * always use the parents tip selection state */
482 if (eBone->parent && (eBone->flag & BONE_CONNECTED)) {
483 eBone->flag &= ~BONE_ROOTSEL;
484 }
485 }
486
487 copy_v3_v3(eBone->head, curBone->arm_head);
488 copy_v3_v3(eBone->tail, curBone->arm_tail);
489 eBone->roll = curBone->arm_roll;
490
491 /* rest of stuff copy */
492 eBone->length = curBone->length;
493 eBone->dist = curBone->dist;
494 eBone->weight = curBone->weight;
495 eBone->xwidth = curBone->xwidth;
496 eBone->zwidth = curBone->zwidth;
497 eBone->rad_head = curBone->rad_head;
498 eBone->rad_tail = curBone->rad_tail;
499 eBone->segments = curBone->segments;
500 eBone->layer = curBone->layer;
501
502 /* Bendy-Bone parameters */
503 eBone->roll1 = curBone->roll1;
504 eBone->roll2 = curBone->roll2;
505 eBone->curve_in_x = curBone->curve_in_x;
506 eBone->curve_in_z = curBone->curve_in_z;
507 eBone->curve_out_x = curBone->curve_out_x;
508 eBone->curve_out_z = curBone->curve_out_z;
509 eBone->ease1 = curBone->ease1;
510 eBone->ease2 = curBone->ease2;
511
512 copy_v3_v3(eBone->scale_in, curBone->scale_in);
513 copy_v3_v3(eBone->scale_out, curBone->scale_out);
514
515 eBone->bbone_prev_type = curBone->bbone_prev_type;
516 eBone->bbone_next_type = curBone->bbone_next_type;
517
518 eBone->bbone_mapping_mode = eBone_BBoneMappingMode(curBone->bbone_mapping_mode);
519 eBone->bbone_flag = curBone->bbone_flag;
520 eBone->bbone_prev_flag = curBone->bbone_prev_flag;
521 eBone->bbone_next_flag = curBone->bbone_next_flag;
522
523 eBone->color = curBone->color;
524 copy_bonecollection_membership(eBone, curBone);
525
526 if (curBone->prop) {
527 eBone->prop = IDP_CopyProperty(curBone->prop);
528 }
529 if (curBone->system_properties) {
530 eBone->system_properties = IDP_CopyProperty(curBone->system_properties);
531 }
532
533 BLI_addtail(edbo, eBone);
534
535 /* Add children if necessary. */
536 if (curBone->childbase.first) {
537 eBoneTest = make_boneList_recursive(edbo, &curBone->childbase, eBone, actBone);
538 if (eBoneTest) {
539 eBoneAct = eBoneTest;
540 }
541 }
542
543 if (curBone == actBone) {
544 eBoneAct = eBone;
545 }
546 }
547
548 return eBoneAct;
549}
550
552{
553 if (link != nullptr) {
554 LISTBASE_FOREACH (EditBone *, ebone, edbo) {
555 if (ebone->temp.bone == link) {
556 return ebone;
557 }
558 }
559 }
560
561 return nullptr;
562}
563
564EditBone *make_boneList(ListBase *edbo, ListBase *bones, Bone *actBone)
565{
566 BLI_assert(!edbo->first && !edbo->last);
567
568 EditBone *active = make_boneList_recursive(edbo, bones, nullptr, actBone);
569
570 LISTBASE_FOREACH (EditBone *, ebone, edbo) {
571 Bone *bone = ebone->temp.bone;
572
573 /* Convert custom B-Bone handle links. */
574 ebone->bbone_prev = find_ebone_link(edbo, bone->bbone_prev);
575 ebone->bbone_next = find_ebone_link(edbo, bone->bbone_next);
576 }
577
578 return active;
579}
580
593static void armature_finalize_restpose(ListBase *bonelist, ListBase *editbonelist)
594{
595 LISTBASE_FOREACH (Bone *, curBone, bonelist) {
596 /* Set bone's local head/tail.
597 * Note that it's important to use final parent's rest-pose (arm_mat) here,
598 * instead of setting those values from edit-bone's matrix (see #46010). */
599 if (curBone->parent) {
600 float parmat_inv[4][4];
601
602 invert_m4_m4(parmat_inv, curBone->parent->arm_mat);
603
604 /* Get the new head and tail */
605 sub_v3_v3v3(curBone->head, curBone->arm_head, curBone->parent->arm_tail);
606 sub_v3_v3v3(curBone->tail, curBone->arm_tail, curBone->parent->arm_tail);
607
608 mul_mat3_m4_v3(parmat_inv, curBone->head);
609 mul_mat3_m4_v3(parmat_inv, curBone->tail);
610 }
611 else {
612 copy_v3_v3(curBone->head, curBone->arm_head);
613 copy_v3_v3(curBone->tail, curBone->arm_tail);
614 }
615
616 /* Set local matrix and arm_mat (rest-pose).
617 * Do not recurse into children here, armature_finalize_restpose() is already recursive. */
618 BKE_armature_where_is_bone(curBone, curBone->parent, false);
619
620 /* Find the associated editbone */
621 LISTBASE_FOREACH (EditBone *, ebone, editbonelist) {
622 if (ebone->temp.bone == curBone) {
623 float premat[3][3];
624 float postmat[3][3];
625 float difmat[3][3];
626 float imat[3][3];
627
628 /* Get the ebone premat and its inverse. */
629 ED_armature_ebone_to_mat3(ebone, premat);
630 invert_m3_m3(imat, premat);
631
632 /* Get the bone postmat. */
633 copy_m3_m4(postmat, curBone->arm_mat);
634
635 mul_m3_m3m3(difmat, imat, postmat);
636
637#if 0
638 printf("Bone %s\n", curBone->name);
639 print_m4("premat", premat);
640 print_m4("postmat", postmat);
641 print_m4("difmat", difmat);
642 printf("Roll = %f\n", RAD2DEGF(-atan2(difmat[2][0], difmat[2][2])));
643#endif
644
645 curBone->roll = -atan2f(difmat[2][0], difmat[2][2]);
646
647 /* And set rest-position again. */
648 BKE_armature_where_is_bone(curBone, curBone->parent, false);
649 break;
650 }
651 }
652
653 /* Recurse into children... */
654 armature_finalize_restpose(&curBone->childbase, editbonelist);
655 }
656}
657
659{
660 Bone *newBone;
661 Object *obt;
662
663 /* armature bones */
666 arm->act_bone = nullptr;
667
668 /* Avoid (almost) zero sized bones, this gives unstable rest-poses. */
669 {
670 /* If this threshold is adjusted, also update the `bl_animation_armature.py` test. */
671 constexpr float bone_length_threshold = 0.000001f;
672 constexpr float bone_length_threshold_sq = bone_length_threshold * bone_length_threshold;
673 constexpr float adjusted_bone_length = 2 * bone_length_threshold;
674
675 /* Build a map from parent to its children, to speed up the loop below. */
677 LISTBASE_FOREACH (EditBone *, eBone, arm->edbo) {
678 parent_to_children.lookup_or_add_default(eBone->parent).add_new(eBone);
679 }
680
681 LISTBASE_FOREACH (EditBone *, eBone, arm->edbo) {
682 const float len_sq = len_squared_v3v3(eBone->head, eBone->tail);
683 if (len_sq > bone_length_threshold_sq) {
684 continue;
685 }
686
687 /* Move the tail away from the head, to ensure the bone has at least some length.
688 * Historical note: until 5.0, Blender used to delete these bones. However, this was an issue
689 * with importers that assume that the bones they import actually will exist on the Armature.
690 * So instead, the bones are elongated a bit for numerical stability. These are very small
691 * adjustments, and so are unlikely to cause issues in practice. */
692
693 float offset[3];
694 if (len_sq == 0.0f) {
695 /* The bone is actually zero-length, which means it has no direction. Just pick one. */
696 offset[0] = 0.0f;
697 offset[1] = 0.0f;
698 offset[2] = adjusted_bone_length;
699 }
700 else {
701 sub_v3_v3v3(offset, eBone->tail, eBone->head);
702 normalize_v3_length(offset, adjusted_bone_length);
703 }
704
705 /* Apply this offset to the bone's tail to make it long enough for numerical stability. And
706 * disconnect it so that the children don't have to be updated, and can remain at their
707 * current location.
708 *
709 * Disconnecting the children is a lot simpler than the alternative: offsetting the children
710 * themselves. That would create subtle issues, for example if there are two bone chains that
711 * would initially exactly align, but one of them has a tiny bone; if all children were
712 * shifted, they would no longer align. */
713 add_v3_v3v3(eBone->tail, eBone->head, offset);
714 if (G.debug & G_DEBUG) {
715 printf("Warning: elongated (almost) zero sized bone: %s\n", eBone->name);
716 }
717
718 blender::VectorSet<EditBone *> *children = parent_to_children.lookup_ptr(eBone);
719 if (children) {
720 for (EditBone *child : *children) {
721 child->flag &= ~BONE_CONNECTED;
722 }
723 }
724 }
725 }
726
727 /* Copy the bones from the edit-data into the armature. */
728 LISTBASE_FOREACH (EditBone *, eBone, arm->edbo) {
729 newBone = MEM_callocN<Bone>("bone");
730 eBone->temp.bone = newBone; /* Associate the real Bones with the EditBones */
731
732 STRNCPY_UTF8(newBone->name, eBone->name);
733 copy_v3_v3(newBone->arm_head, eBone->head);
734 copy_v3_v3(newBone->arm_tail, eBone->tail);
735 newBone->arm_roll = eBone->roll;
736
737 newBone->flag = eBone->flag;
738 newBone->inherit_scale_mode = eBone->inherit_scale_mode;
739 newBone->drawtype = eBone->drawtype;
740
741 if (eBone == arm->act_edbone) {
742 /* Don't change active selection, this messes up separate which uses
743 * edit-mode toggle and can separate active bone which is de-selected originally. */
744
745 /* important, edit-bones can be active with only 1 point selected */
746 /* `newBone->flag |= BONE_SELECTED;` */
747 arm->act_bone = newBone;
748 }
749 newBone->roll = 0.0f;
750
751 newBone->weight = eBone->weight;
752 newBone->dist = eBone->dist;
753
754 newBone->xwidth = eBone->xwidth;
755 newBone->zwidth = eBone->zwidth;
756 newBone->rad_head = eBone->rad_head;
757 newBone->rad_tail = eBone->rad_tail;
758 newBone->segments = eBone->segments;
759 newBone->layer = eBone->layer;
760
761 /* Bendy-Bone parameters */
762 newBone->roll1 = eBone->roll1;
763 newBone->roll2 = eBone->roll2;
764 newBone->curve_in_x = eBone->curve_in_x;
765 newBone->curve_in_z = eBone->curve_in_z;
766 newBone->curve_out_x = eBone->curve_out_x;
767 newBone->curve_out_z = eBone->curve_out_z;
768 newBone->ease1 = eBone->ease1;
769 newBone->ease2 = eBone->ease2;
770 copy_v3_v3(newBone->scale_in, eBone->scale_in);
771 copy_v3_v3(newBone->scale_out, eBone->scale_out);
772
773 newBone->bbone_prev_type = eBone->bbone_prev_type;
774 newBone->bbone_next_type = eBone->bbone_next_type;
775
776 newBone->bbone_mapping_mode = eBone->bbone_mapping_mode;
777 newBone->bbone_flag = eBone->bbone_flag;
778 newBone->bbone_prev_flag = eBone->bbone_prev_flag;
779 newBone->bbone_next_flag = eBone->bbone_next_flag;
780
781 newBone->color = eBone->color;
782
783 LISTBASE_FOREACH (BoneCollectionReference *, ref, &eBone->bone_collections) {
785 "ED_armature_from_edit", *ref);
786 BLI_addtail(&newBone->runtime.collections, newBoneRef);
787 }
788
789 if (eBone->prop) {
790 newBone->prop = IDP_CopyProperty(eBone->prop);
791 }
792 if (eBone->system_properties) {
793 newBone->system_properties = IDP_CopyProperty(eBone->system_properties);
794 }
795 }
796
797 /* Fix parenting in a separate pass to ensure ebone->bone connections are valid at this point.
798 * Do not set bone->head/tail here anymore,
799 * using EditBone data for that is not OK since our later fiddling with parent's arm_mat
800 * (for roll conversion) may have some small but visible impact on locations (#46010). */
801 LISTBASE_FOREACH (EditBone *, eBone, arm->edbo) {
802 newBone = eBone->temp.bone;
803 if (eBone->parent) {
804 newBone->parent = eBone->parent->temp.bone;
805 BLI_addtail(&newBone->parent->childbase, newBone);
806 }
807 /* ...otherwise add this bone to the armature's bonebase */
808 else {
809 BLI_addtail(&arm->bonebase, newBone);
810 }
811
812 /* Also transfer B-Bone custom handles. */
813 if (eBone->bbone_prev) {
814 newBone->bbone_prev = eBone->bbone_prev->temp.bone;
815 }
816 if (eBone->bbone_next) {
817 newBone->bbone_next = eBone->bbone_next->temp.bone;
818 }
819 }
820
821 /* Finalize definition of rest-pose data (roll, bone_mat, arm_mat, head/tail...). */
824
826
827 /* so all users of this armature should get rebuilt */
828 for (obt = static_cast<Object *>(bmain->objects.first); obt;
829 obt = static_cast<Object *>(obt->id.next))
830 {
831 if (obt->data == arm) {
832 BKE_pose_rebuild(bmain, obt, arm, true);
833 }
834 }
835
836 DEG_id_tag_update(&arm->id, 0);
837}
838
840{
841 /* Clear the edit-bones list. */
842 if (arm->edbo) {
843 if (arm->edbo->first) {
844 LISTBASE_FOREACH (EditBone *, eBone, arm->edbo) {
845 if (eBone->prop) {
846 IDP_FreeProperty(eBone->prop);
847 }
848 if (eBone->system_properties) {
849 IDP_FreeProperty(eBone->system_properties);
850 }
851 BLI_freelistN(&eBone->bone_collections);
852 }
853
854 BLI_freelistN(arm->edbo);
855 }
856 MEM_freeN(arm->edbo);
857 arm->edbo = nullptr;
858 arm->act_edbone = nullptr;
859 }
860}
861
863{
865 arm->edbo = MEM_callocN<ListBase>("edbo armature");
866 arm->act_edbone = make_boneList(arm->edbo, &arm->bonebase, arm->act_bone);
867}
868
870
871/* -------------------------------------------------------------------- */
874
875void ED_armature_ebone_listbase_free(ListBase *lb, const bool do_id_user)
876{
877 EditBone *ebone, *ebone_next;
878
879 for (ebone = static_cast<EditBone *>(lb->first); ebone; ebone = ebone_next) {
880 ebone_next = ebone->next;
881
882 if (ebone->prop) {
883 IDP_FreeProperty_ex(ebone->prop, do_id_user);
884 }
885 if (ebone->system_properties) {
886 IDP_FreeProperty_ex(ebone->system_properties, do_id_user);
887 }
888
890
891 MEM_freeN(ebone);
892 }
893
895}
896
897void ED_armature_ebone_listbase_copy(ListBase *lb_dst, ListBase *lb_src, const bool do_id_user)
898{
900
901 LISTBASE_FOREACH (EditBone *, ebone_src, lb_src) {
902 EditBone *ebone_dst = static_cast<EditBone *>(MEM_dupallocN(ebone_src));
903 if (ebone_dst->prop) {
904 ebone_dst->prop = IDP_CopyProperty_ex(ebone_dst->prop,
905 do_id_user ? 0 : LIB_ID_CREATE_NO_USER_REFCOUNT);
906 }
907 if (ebone_dst->system_properties) {
909 ebone_dst->system_properties, do_id_user ? 0 : LIB_ID_CREATE_NO_USER_REFCOUNT);
910 }
911 ebone_src->temp.ebone = ebone_dst;
912 BLI_addtail(lb_dst, ebone_dst);
913 }
914
915 /* set pointers */
916 LISTBASE_FOREACH (EditBone *, ebone_dst, lb_dst) {
917 if (ebone_dst->parent) {
918 ebone_dst->parent = ebone_dst->parent->temp.ebone;
919 }
920 if (ebone_dst->bbone_next) {
921 ebone_dst->bbone_next = ebone_dst->bbone_next->temp.ebone;
922 }
923 if (ebone_dst->bbone_prev) {
924 ebone_dst->bbone_prev = ebone_dst->bbone_prev->temp.ebone;
925 }
926
927 BLI_duplicatelist(&ebone_dst->bone_collections, &ebone_dst->bone_collections);
928 }
929}
930
932{
933 /* be sure they don't hang ever */
934 LISTBASE_FOREACH (EditBone *, ebone, lb) {
935 ebone->temp.p = nullptr;
936 }
937}
938
940
941/* -------------------------------------------------------------------- */
947
949{
950 if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
951 return ((ebone->flag & (BONE_SELECTED | BONE_TIPSEL)) |
952 ((ebone->parent->flag & BONE_TIPSEL) ? BONE_ROOTSEL : 0));
953 }
954 return (ebone->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL));
955}
956
958{
960
961 if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
963 ebone->parent->flag &= ~BONE_TIPSEL;
964
965 ebone->flag |= flag;
966 ebone->parent->flag |= (flag & BONE_ROOTSEL) ? BONE_TIPSEL : 0;
967 }
968 else {
970 ebone->flag |= flag;
971 }
972}
973
979
985
987{
988 /* NOTE: this function could be used in more places. */
989
990 int flag;
991 if (select) {
992 BLI_assert((ebone->flag & BONE_UNSELECTABLE) == 0);
994 }
995 else {
996 flag = 0;
997 }
999}
1000
Functions to deal with Armatures.
C++ functions to deal with Armature collections (i.e. the successor of bone layers).
void ANIM_armature_bonecoll_reconstruct(bArmature *armature)
void BKE_armature_bone_hash_make(bArmature *arm)
void BKE_pose_rebuild(Main *bmain, Object *ob, bArmature *arm, bool do_id_user)
void BKE_armature_bonelist_free(ListBase *lb, bool do_id_user)
void BKE_armature_where_is_bone(Bone *bone, const Bone *bone_parent, bool use_recursion)
void mat3_to_vec_roll(const float mat[3][3], float r_vec[3], float *r_roll)
void BKE_armature_bone_hash_free(bArmature *arm)
void vec_roll_to_mat3_normalized(const float nor[3], float roll, float r_mat[3][3])
@ G_DEBUG
void IDP_FreeProperty(IDProperty *prop)
Definition idprop.cc:1251
IDProperty * IDP_CopyProperty_ex(const IDProperty *prop, int flag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:845
IDProperty * IDP_CopyProperty(const IDProperty *prop) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:863
void IDP_FreeProperty_ex(IDProperty *prop, bool do_id_user)
Definition idprop.cc:1245
@ LIB_ID_CREATE_NO_USER_REFCOUNT
#define BLI_assert(a)
Definition BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(ListBase *lb)
void * BLI_findstring(const ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:608
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
void BLI_freelinkN(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:270
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:497
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
void void void void void void BLI_duplicatelist(ListBase *dst, const ListBase *src) ATTR_NONNULL(1
#define BLI_ASSERT_UNIT_M3(m)
#define RAD2DEGF(_rad)
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])
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 add_v3_v3v3(float r[3], const float a[3], const float b[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_length(float n[3], float unit_length)
MINLINE float normalize_v3(float n[3])
#define STRNCPY_UTF8(dst, src)
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)
BMesh const char void * data
const Value * lookup_ptr(const Key &key) const
Definition BLI_map.hh:508
Value & lookup_or_add_default(const Key &key)
Definition BLI_map.hh:639
#define offsetof(t, d)
#define active
#define printf(...)
#define select(A, B, C)
int count
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_dupallocN(const void *vmemh)
Definition mallocn.cc:143
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
ccl_device_inline float3 atan2(const float3 y, const float3 x)
#define G(x, y, z)
bool bone_is_visible(const bArmature *armature, const Bone *bone)
const char * name
#define atan2f
float curve_in_z
int8_t drawtype
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
IDProperty * system_properties
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
union EditBone::@275371335250266324235150226366250166246037204077 temp
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
char bbone_next_type
IDProperty * system_properties
float rad_tail
EditBone * ebone
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:417
void * last
void * first
ListBase objects
Definition BKE_main.hh:280
struct EditBone * act_edbone
ListBase * edbo
i
Definition text_draw.cc:230
uint len
uint8_t flag
Definition wm_window.cc:145