45constexpr auto bonecoll_default_name =
"Bones";
55 if (name ==
nullptr || name[0] ==
'\0') {
57 name =
DATA_(bonecoll_default_name);
65 bcoll->
flags = default_flags;
67 bcoll->
prop =
nullptr;
75 "bone collection still has bones assigned to it, will cause dangling pointers in "
93 BLI_addtail(&member->bone->runtime.collections, ref);
117 [&](
Bone *bone) { BLI_freelistN(&bone->runtime.collections); });
127 struct DupNameCheckData {
134 auto bonecoll_name_is_duplicate = [](
void *arg,
const char *name) ->
bool {
135 DupNameCheckData *data =
static_cast<DupNameCheckData *
>(arg);
137 if (bcoll != data->bcoll &&
STREQ(bcoll->
name, name)) {
144 DupNameCheckData check_data = {armature, bcoll};
147 DATA_(bonecoll_default_name),
150 sizeof(bcoll->
name));
162 BLI_assert(index <= armature->collection_array_num);
186 BLI_assert(at_index <= armature->collection_root_count);
199 const int parent_index)
201 BLI_assert_msg(parent_index >= 0,
"Armature bone collection index should be 0 or larger");
203 "Parent bone collection index should not point beyond the end of the array");
216 return insert_at_index;
221 const int parent_index)
232 if (parent_index < 0) {
294 const int parent_bcoll_dst_index,
298 "this function can only add children to another collection, it cannot add roots");
315 for (
int bcoll_src_index = parent_bcoll_src->
child_index;
323 armature_dst, bcoll_dst, parent_bcoll_dst_index);
328 "expecting children to be added to the array AFTER their parent");
330 (void)bcoll_index_dst;
340 BLI_assert_msg(new_parent_bcoll_dst_index == parent_bcoll_dst_index,
341 "did not expect parent_bcoll_dst_index to change");
346 "all children should have been copied");
347 for (
int child_num = 0; child_num < parent_bcoll_dst->
child_count; child_num++) {
348 const int bcoll_src_index = parent_bcoll_src->
child_index + child_num;
349 const int bcoll_dst_index = parent_bcoll_dst->
child_index + child_num;
368 "Armature \"%s\" has library override operation that adds non-root bone collection "
369 "\"%s\". This is unexpected, please file a bug report.\n",
370 armature_src->
id.
name + 2,
371 bcoll_to_copy->
name);
378 const int bcoll_index = anchor_index + 1;
380 bcoll_index <= armature_dst->collection_root_count,
381 "did not expect library override to add a child bone collection, only roots are expected");
402 if (bcoll ==
nullptr) {
442 if (active_name.empty()) {
449 if (bcoll->name == active_name) {
481 const int from_index,
485 from_index == to_index)
498 if (parent_index < 0) {
507 const int old_parent_child_index = parent_bcoll->
child_index;
511 parent_bcoll->
child_index = old_parent_child_index;
517 const int parent_bcoll_index,
518 const int bcoll_index)
520 if (parent_bcoll_index < 0) {
531 const int from_index,
538 if (from_parent_index != to_parent_index) {
546 armature, from_index, to_child_num, from_parent_index, to_parent_index);
550 switch (before_after) {
552 if (to_index > from_index) {
559 if (to_index < from_index) {
574 if (bcoll ==
nullptr) {
579 const int to_index = bcoll_index + step;
591 char old_name[
sizeof(bcoll->
name)];
595 if (name[0] ==
'\0') {
614 BLI_assert(0 <= index && index < armature->collection_array_num);
643 BLI_assert_msg(index >= 0,
"could not find bone collection after moving things around");
645 if (parent_bcoll_index >= 0) {
647 armature, parent_bcoll, parent_bcoll_index);
649 "could not find bone collection parent after moving things around");
656 if (parent_bcoll_index < 0) {
677 if (active_collection_index >= 0) {
686 else if (active_collection_index > 0 &&
688 armature, parent_bcoll_index, active_collection_index - 1))
700 const bool is_solo = bcoll->is_solo();
715template<
typename MaybeConstBoneCollection>
719 for (MaybeConstBoneCollection *bcoll : bonecolls) {
720 if (
STREQ(bcoll->name, name)) {
746 for (
BoneCollection *bcoll : armature->collection_children(parent_bcoll)) {
747 bcoll->
flags &= ~BONE_COLLECTION_ANCESTORS_VISIBLE;
755 if (!parent_bcoll->is_visible_with_ancestors()) {
765 for (
BoneCollection *bcoll : armature->collection_children(parent_bcoll)) {
776 if (parent_bcoll ==
nullptr || parent_bcoll->is_visible_with_ancestors()) {
780 bcoll->
flags &= ~BONE_COLLECTION_ANCESTORS_VISIBLE;
793 bcoll->
flags &= ~BONE_COLLECTION_VISIBLE;
799 const bool is_visible)
822 bcoll->
flags &= ~BONE_COLLECTION_SOLO;
828 bool any_bcoll_solo =
false;
829 for (
const BoneCollection *bcoll : armature->collections_span()) {
831 any_bcoll_solo =
true;
836 if (any_bcoll_solo) {
840 armature->
flag &= ~ARM_BCOLL_SOLO_ACTIVE;
849 if (is_solo_active) {
851 return bcoll->is_solo();
854 return bcoll->is_visible_with_ancestors();
863 bcoll->
flags &= ~BONE_COLLECTION_EXPANDED;
886 if (member->bone == bone) {
901 if (ref->bcoll == bcoll) {
930 bool was_found =
false;
934 if (member->bone == bone) {
945 if (ref->bcoll == bcoll) {
972 bool was_found =
false;
976 if (ref->bcoll == bcoll) {
994 LISTBASE_FOREACH (BoneCollectionReference *, ref, &bone->runtime.collections) {
995 add_membership(ref->bcoll, bone);
1057 if (bcoll == bcoll_ref->bcoll) {
1067 if (armature->
edbo) {
1122 for (
const BoneCollection *arm_bcoll : armature->collections_span()) {
1123 if (arm_bcoll == bcoll) {
1134 if (bcoll_index < armature->collection_root_count) {
1140 for (
const BoneCollection *potential_parent : armature->collections_span()) {
1141 if (potential_parent->child_index <= bcoll_index &&
1142 bcoll_index < potential_parent->child_index + potential_parent->child_count)
1162 int new_child_number)
1171 if (parent_index < 0) {
1172 parent_bcoll = &fake_armature_parent;
1179 if (new_child_number >= parent_bcoll->
child_count) {
1182 if (new_child_number < 0) {
1188 const int old_parent_child_index = parent_bcoll->
child_index;
1189 const int to_index = parent_bcoll->
child_index + new_child_number;
1192 parent_bcoll->
child_index = old_parent_child_index;
1209 const int potential_parent_index,
1210 const int potential_child_index)
1214 return potential_parent_index == -1;
1216 if (potential_parent_index < 0) {
1223 return potential_parent->
child_index <= potential_child_index &&
1224 potential_child_index < upper_bound;
1228 const int potential_parent_index,
1229 const int potential_descendant_index)
1232 "Potential descendant has to exist for this function call to make sense.");
1243 for (
int visit_index = potential_parent->
child_index; visit_index < upper_bound; visit_index++) {
1268 auto find_old = [bcolls_source](
const char *name,
const int index) ->
const BoneCollection * {
1270 if (index < bcolls_source.
size()) {
1284 for (
int i = 0; i < bcolls_dest.
size(); i++) {
1297 const int from_bcoll_index,
1299 const int from_parent_index,
1300 const int to_parent_index)
1302 BLI_assert(0 <= from_bcoll_index && from_bcoll_index < armature->collection_array_num);
1303 BLI_assert(-1 <= from_parent_index && from_parent_index < armature->collection_array_num);
1304 BLI_assert(-1 <= to_parent_index && to_parent_index < armature->collection_array_num);
1306 if (from_parent_index == to_parent_index) {
1308 return from_bcoll_index;
1317 armature_root.
flags = default_flags;
1325 BLI_assert_msg(-1 <= to_child_num && to_child_num <= to_parent->child_count,
1326 "to_child_num must point to an index of a child of the new parent, or the index "
1327 "of the last child + 1, or be -1 to indicate 'after last child'");
1328 if (to_child_num < 0) {
1339 to_bcoll_index = to_parent->
child_index + to_child_num;
1344 if (to_bcoll_index > from_bcoll_index) {
1352 const bool needs_post_move_child_index_bump = from_parent->
child_index == from_bcoll_index &&
1353 to_bcoll_index <= from_bcoll_index;
1356 const bool becomes_new_first_child = to_child_num == 0 || to_parent->
child_count == 0;
1365 else if (needs_post_move_child_index_bump) {
1376 if (becomes_new_first_child) {
1388 return to_bcoll_index;
1395 int *bcoll_array_dst_num,
1397 const int bcoll_array_src_num,
1398 const bool do_id_user)
1405 *bcoll_array_dst_num = bcoll_array_src_num;
1408 for (
int i = 0; i < bcoll_array_src_num; i++) {
1415 if (bcoll_src->
prop) {
1420 (*bcoll_array_dst)[i] = bcoll_dst;
1422 bcoll_map.add(bcoll_src, bcoll_dst);
1429 int *bcoll_array_num,
1430 const bool do_id_user)
1432 for (
int i = 0; i < *bcoll_array_num; i++) {
1450 *bcoll_array_num = 0;
1457 const int start_index,
1459 const int direction)
1461 BLI_assert_msg(direction == 1 || direction == -1,
"`direction` must be either -1 or +1");
1477 const int move_from_index = (direction > 0 ? start_index +
count : start_index - 1);
1478 const int move_to_index = (direction > 0 ? start_index : start_index +
count - 1);
1490 if (bcoll->child_index == 0 && bcoll->child_count == 0) {
1496 if (start_index <= bcoll->child_index && bcoll->child_index < start_index +
count) {
1503 if (active_index == move_from_index) {
1506 else if (start_index <= active_index && active_index < start_index +
count) {
1513 if (from_index == to_index) {
1518 BLI_assert(from_index < armature->collection_array_num);
1520 BLI_assert(to_index < armature->collection_array_num);
1522 if (from_index < to_index) {
1523 const int block_start_index = from_index + 1;
1524 const int block_count = to_index - from_index;
1528 const int block_start_index = to_index;
1529 const int block_count = from_index - to_index;
1538 if (collections[index] == bcoll) {
1541 if (index > 0 && collections[index - 1] == bcoll) {
1544 if (index < armature->collection_array_num - 1 && collections[index + 1] == bcoll) {
1552 printf(
"\033[38;5;214mBone collections of armature \"%s\":\033[0m\n", armature->
id.
name + 2);
1553 constexpr int root_ansi_color = 95;
1558 printf(
" - \033[%dmcolls[%d] = %24s\033[0m ",
1559 i < armature->collection_root_count ? root_ansi_color : 0,
1578 if (armature->
edbo) {
C++ functions to deal with Armature collections (i.e. the successor of bone layers).
void ANIM_armature_bonecoll_is_expanded_set(BoneCollection *bcoll, bool is_expanded)
bool ANIM_armature_bonecoll_unassign_editbone(BoneCollection *bcoll, EditBone *ebone)
void ANIM_bonecoll_free(BoneCollection *bcoll, bool do_id_user_count=true)
bool ANIM_armature_bonecoll_unassign(BoneCollection *bcoll, Bone *bone)
void ANIM_armature_bonecoll_active_index_set(bArmature *armature, int bone_collection_index)
void BKE_animdata_fix_paths_rename_all(struct ID *ref_id, const char *prefix, const char *oldName, const char *newName)
Bone * BKE_armature_find_bone_name(bArmature *arm, const char *name)
IDProperty * IDP_CopyProperty_ex(const IDProperty *prop, int flag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
void IDP_FreeProperty_ex(IDProperty *prop, bool do_id_user)
@ LIB_ID_CREATE_NO_USER_REFCOUNT
bool BKE_lib_override_library_is_system_defined(const Main *bmain, const ID *id)
#define BLI_assert_msg(a, msg)
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
#define LISTBASE_FOREACH(type, var, list)
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
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)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
#define STRNCPY(dst, src)
#define STRNCPY_UTF8(dst, src)
size_t void BLI_uniquename_cb(UniquenameCheckCallback unique_check, void *arg, const char *defname, char delim, char *name, size_t name_maxncpy) ATTR_NONNULL(1
#define ID_IS_LINKED(_id)
#define ID_IS_OVERRIDE_LIBRARY(_id)
@ BONE_COLLECTION_VISIBLE
@ BONE_COLLECTION_SELECTABLE
@ BONE_COLLECTION_ANCESTORS_VISIBLE
@ BONE_COLLECTION_EXPANDED
@ BONE_COLLECTION_OVERRIDE_LIBRARY_LOCAL
Read Guarded memory(de)allocation.
void ANIM_armature_bonecoll_unassign_all_editbone(EditBone *ebone)
void ANIM_armature_refresh_solo_active(bArmature *armature)
static void add_membership(BoneCollection *bcoll, Bone *bone)
void ANIM_armature_runtime_free(bArmature *armature)
void ANIM_armature_bonecoll_remove_from_index(bArmature *armature, int index)
bool ANIM_armature_bonecoll_assign_and_move(BoneCollection *bcoll, Bone *bone)
void ANIM_armature_bonecoll_active_set(bArmature *armature, BoneCollection *bcoll)
static void bonecoll_insert_at_index(bArmature *armature, BoneCollection *bcoll, const int index)
static void bonecoll_insert_as_root(bArmature *armature, BoneCollection *bcoll, int at_index)
void ANIM_armature_bonecoll_is_visible_set(bArmature *armature, BoneCollection *bcoll, const bool is_visible)
void ANIM_armature_bonecoll_hide_all(bArmature *armature)
bool ANIM_armature_bonecoll_is_editable(const bArmature *armature, const BoneCollection *bcoll)
static void ancestors_visible_update(bArmature *armature, const BoneCollection *parent_bcoll, BoneCollection *bcoll)
BoneCollection * ANIM_armature_bonecoll_insert_copy_after(bArmature *armature_dst, const bArmature *armature_src, const BoneCollection *anchor_in_dst, const BoneCollection *bcoll_to_copy)
bool ANIM_armature_bonecoll_assign_and_move_editbone(BoneCollection *bcoll, EditBone *ebone)
void ANIM_armature_bonecoll_is_expanded_set(BoneCollection *bcoll, bool is_expanded)
void ANIM_armature_bonecoll_active_index_set(bArmature *armature, const int bone_collection_index)
void ANIM_bonecoll_hide(bArmature *armature, BoneCollection *bcoll)
bool ANIM_armature_bonecoll_move(bArmature *armature, BoneCollection *bcoll, const int step)
static bool any_bone_collection_visible(const bArmature *armature, const ListBase *collection_refs)
bool ANIM_armature_bonecoll_move_to_index(bArmature *armature, const int from_index, const int to_index)
void ANIM_armature_runtime_refresh(bArmature *armature)
void ANIM_armature_bonecoll_active_name_set(bArmature *armature, const char *name)
void ANIM_armature_bonecoll_show_from_ebone(bArmature *armature, const EditBone *ebone)
static MaybeConstBoneCollection * bonecolls_get_by_name(blender::Span< MaybeConstBoneCollection * > bonecolls, const char *name)
void ANIM_armature_bonecoll_show_from_bone(bArmature *armature, const Bone *bone)
static void ancestors_visible_descendants_clear(bArmature *armature, BoneCollection *parent_bcoll)
BoneCollection * ANIM_armature_bonecoll_get_by_name(bArmature *armature, const char *name)
static int bonecoll_insert_as_child(bArmature *armature, BoneCollection *bcoll, const int parent_index)
bool ANIM_bonecoll_is_visible_editbone(const bArmature *armature, const EditBone *ebone)
static void liboverride_recursively_add_children(bArmature *armature_dst, const bArmature *armature_src, const int parent_bcoll_dst_index, const BoneCollection *parent_bcoll_src)
int ANIM_armature_bonecoll_move_before_after_index(bArmature *armature, const int from_index, int to_index, const MoveLocation before_after)
bool ANIM_armature_bonecoll_unassign_editbone(BoneCollection *bcoll, EditBone *ebone)
static void bonecoll_ensure_name_unique(bArmature *armature, BoneCollection *bcoll)
void ANIM_armature_bonecoll_assign_active(const bArmature *armature, EditBone *ebone)
bool ANIM_armature_bonecoll_assign(BoneCollection *bcoll, Bone *bone)
void ANIM_armature_bonecoll_remove(bArmature *armature, BoneCollection *bcoll)
bool ANIM_armature_bonecoll_unassign(BoneCollection *bcoll, Bone *bone)
void ANIM_armature_bonecoll_unassign_all(Bone *bone)
void ANIM_bonecoll_show(bArmature *armature, BoneCollection *bcoll)
void ANIM_armature_bonecoll_show_from_pchan(bArmature *armature, const bPoseChannel *pchan)
void ANIM_armature_bonecoll_active_runtime_refresh(bArmature *armature)
static int bonecoll_child_number(const bArmature *armature, const int parent_bcoll_index, const int bcoll_index)
static void ancestors_visible_descendants_update(bArmature *armature, BoneCollection *parent_bcoll)
static BoneCollection * copy_and_update_ownership(const bArmature *armature_dst, const BoneCollection *bcoll_to_copy)
BoneCollection * ANIM_bonecoll_new(const char *name)
bool ANIM_armature_bonecoll_is_visible_effectively(const bArmature *armature, const BoneCollection *bcoll)
void ANIM_armature_bonecoll_name_set(bArmature *armature, BoneCollection *bcoll, const char *name)
static void add_reference(Bone *bone, BoneCollection *bcoll)
static bool bcoll_list_contains(const ListBase *collection_refs, const BoneCollection *bcoll)
void ANIM_armature_bonecoll_show_all(bArmature *armature)
void ANIM_armature_bonecoll_solo_set(bArmature *armature, BoneCollection *bcoll, const bool is_solo)
void ANIM_bonecoll_free(BoneCollection *bcoll, const bool do_id_user_count)
void ANIM_armature_bonecoll_reconstruct(bArmature *armature)
bool ANIM_armature_bonecoll_contains_active_bone(const bArmature *armature, const BoneCollection *bcoll)
bool ANIM_bone_in_visible_collection(const bArmature *armature, const Bone *bone)
int ANIM_armature_bonecoll_get_index_by_name(bArmature *armature, const char *name)
static void add_reverse_pointers(BoneCollection *bcoll)
BoneCollection * ANIM_armature_bonecoll_new(bArmature *armature, const char *name, const int parent_index)
static void armature_bonecoll_active_clear(bArmature *armature)
bool ANIM_armature_bonecoll_assign_editbone(BoneCollection *bcoll, EditBone *ebone)
Internal C++ functions to deal with bone collections. These are mostly here for internal use in bone_...
constexpr int64_t size() const
void *(* MEM_reallocN_id)(void *vmemh, size_t len, const char *str)
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
void MEM_freeN(void *vmemh)
void *(* MEM_dupallocN)(const void *vmemh)
void bonecolls_rotate_block(bArmature *armature, const int start_index, const int count, const int direction)
void bonecolls_debug_list(const bArmature *armature)
void bonecoll_unassign_and_free(bArmature *armature, BoneCollection *bcoll)
int bonecolls_find_index_near(bArmature *armature, BoneCollection *bcoll, const int index)
void bonecolls_move_to_index(bArmature *armature, const int from_index, const int to_index)
blender::Map< BoneCollection *, BoneCollection * > ANIM_bonecoll_array_copy_no_membership(BoneCollection ***bcoll_array_dst, int *bcoll_array_dst_num, BoneCollection **bcoll_array_src, int bcoll_array_src_num, bool do_id_user)
bool armature_bonecoll_is_root(const bArmature *armature, int bcoll_index)
static void ANIM_armature_foreach_bone(ListBase *bones, CB callback)
void bonecolls_copy_expanded_flag(Span< BoneCollection * > bcolls_dest, Span< const BoneCollection * > bcolls_source)
int armature_bonecoll_child_number_find(const bArmature *armature, const ::BoneCollection *bcoll)
bool bonecoll_has_children(const BoneCollection *bcoll)
int armature_bonecoll_find_index(const bArmature *armature, const ::BoneCollection *bcoll)
bool armature_bonecoll_is_descendant_of(const bArmature *armature, int potential_parent_index, int potential_descendant_index)
int armature_bonecoll_find_parent_index(const bArmature *armature, int bcoll_index)
int armature_bonecoll_child_number_set(bArmature *armature, ::BoneCollection *bcoll, int new_child_number)
void ANIM_bonecoll_array_free(BoneCollection ***bcoll_array, int *bcoll_array_num, bool do_id_user)
int armature_bonecoll_move_to_parent(bArmature *armature, int from_bcoll_index, int to_child_num, int from_parent_index, int to_parent_index)
bool armature_bonecoll_is_child_of(const bArmature *armature, int potential_parent_index, int potential_child_index)
struct BoneCollection * bcoll
ListBase bone_collections
int active_collection_index
struct BoneCollection * active_collection
int collection_root_count
struct BoneCollection ** collection_array
char active_collection_name[64]
struct EditBone * act_edbone
struct bArmature_Runtime runtime