diff options
-rw-r--r-- | source/blender/blenkernel/BKE_armature.h | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/armature.c | 51 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 12 | ||||
-rw-r--r-- | source/blender/editors/armature/armature_naming.c | 10 | ||||
-rw-r--r-- | source/blender/editors/armature/armature_utils.c | 3 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_armature_types.h | 6 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_armature.c | 25 |
7 files changed, 80 insertions, 31 deletions
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index b5da30e725d..6839e13ffe1 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -84,7 +84,9 @@ bool BKE_pose_minmax( int bone_autoside_name(char name[64], int strip_number, short axis, float head, float tail); struct Bone *BKE_armature_find_bone_name(struct bArmature *arm, const char *name); -struct GHash *BKE_armature_bone_from_name_map(struct bArmature *arm); + +void BKE_armature_bone_hash_make(struct bArmature *arm); +void BKE_armature_bone_hash_free(struct bArmature *arm); bool BKE_armature_bone_flag_test_recursive(const struct Bone *bone, int flag); diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 60446bf60b6..bd9907acb24 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -125,6 +125,7 @@ void BKE_armature_free(bArmature *arm) { BKE_animdata_free(&arm->id, false); + BKE_armature_bone_hash_free(arm); BKE_armature_bonelist_free(&arm->bonebase); /* free editmode data */ @@ -169,25 +170,20 @@ static void copy_bonechildren(Bone *bone_dst, } } -static void copy_bonechildren_custom_handles(Bone *bone_dst, bArmature *arm_dst, GHash **bone_hash) +static void copy_bonechildren_custom_handles(Bone *bone_dst, bArmature *arm_dst) { Bone *bone_dst_child; - /* Lazily create the name -> bone hashtable. */ - if ((bone_dst->bbone_prev || bone_dst->bbone_next) && *bone_hash == NULL) { - *bone_hash = BKE_armature_bone_from_name_map(arm_dst); - } - if (bone_dst->bbone_prev) { - bone_dst->bbone_prev = BLI_ghash_lookup(*bone_hash, bone_dst->bbone_prev->name); + bone_dst->bbone_prev = BKE_armature_find_bone_name(arm_dst, bone_dst->bbone_prev->name); } if (bone_dst->bbone_next) { - bone_dst->bbone_next = BLI_ghash_lookup(*bone_hash, bone_dst->bbone_next->name); + bone_dst->bbone_next = BKE_armature_find_bone_name(arm_dst, bone_dst->bbone_next->name); } for (bone_dst_child = bone_dst->childbase.first; bone_dst_child; bone_dst_child = bone_dst_child->next) { - copy_bonechildren_custom_handles(bone_dst_child, arm_dst, bone_hash); + copy_bonechildren_custom_handles(bone_dst_child, arm_dst); } } @@ -212,6 +208,8 @@ void BKE_armature_copy_data(Main *UNUSED(bmain), /* We never handle usercount here for own data. */ const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT; + arm_dst->bonehash = NULL; + BLI_duplicatelist(&arm_dst->bonebase, &arm_src->bonebase); /* Duplicate the childrens' lists */ @@ -224,15 +222,11 @@ void BKE_armature_copy_data(Main *UNUSED(bmain), arm_dst->act_bone = bone_dst_act; - /* Fix custom handle references. */ - GHash *bone_hash = NULL; /* lazily created */ + BKE_armature_bone_hash_make(arm_dst); + /* Fix custom handle references. */ for (bone_dst = arm_dst->bonebase.first; bone_dst; bone_dst = bone_dst->next) { - copy_bonechildren_custom_handles(bone_dst, arm_dst, &bone_hash); - } - - if (bone_hash) { - BLI_ghash_free(bone_hash, NULL, NULL); + copy_bonechildren_custom_handles(bone_dst, arm_dst); } arm_dst->edbo = NULL; @@ -274,6 +268,10 @@ Bone *BKE_armature_find_bone_name(bArmature *arm, const char *name) return NULL; } + if (arm->bonehash) { + return BLI_ghash_lookup(arm->bonehash, name); + } + return get_named_bone_bonechildren(&arm->bonebase, name); } @@ -291,7 +289,7 @@ static void armature_bone_from_name_insert_recursive(GHash *bone_hash, ListBase * \note typically #bPose.chanhash us used via #BKE_pose_channel_find_name * this is for the cases we can't use pose channels. */ -GHash *BKE_armature_bone_from_name_map(bArmature *arm) +static GHash *armature_bone_from_name_map(bArmature *arm) { const int bones_count = BKE_armature_bonelist_count(&arm->bonebase); GHash *bone_hash = BLI_ghash_str_new_ex(__func__, bones_count); @@ -299,6 +297,21 @@ GHash *BKE_armature_bone_from_name_map(bArmature *arm) return bone_hash; } +void BKE_armature_bone_hash_make(bArmature *arm) +{ + if (!arm->bonehash) { + arm->bonehash = armature_bone_from_name_map(arm); + } +} + +void BKE_armature_bone_hash_free(bArmature *arm) +{ + if (arm->bonehash) { + BLI_ghash_free(arm->bonehash, NULL, NULL); + arm->bonehash = NULL; + } +} + bool BKE_armature_bone_flag_test_recursive(const Bone *bone, int flag) { if (bone->flag & flag) { @@ -2458,11 +2471,9 @@ void BKE_pose_clear_pointers(bPose *pose) void BKE_pose_remap_bone_pointers(bArmature *armature, bPose *pose) { - GHash *bone_hash = BKE_armature_bone_from_name_map(armature); for (bPoseChannel *pchan = pose->chanbase.first; pchan; pchan = pchan->next) { - pchan->bone = BLI_ghash_lookup(bone_hash, pchan->name); + pchan->bone = BKE_armature_find_bone_name(armature, pchan->name); } - BLI_ghash_free(bone_hash, NULL, NULL); } /** Find the matching pose channel using the bone name, if not NULL. */ diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 400070f12fc..f0e70f1be27 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3763,9 +3763,6 @@ static void lib_link_pose(FileData *fd, Main *bmain, Object *ob, bPose *pose) } } - /* avoid string */ - GHash *bone_hash = BKE_armature_bone_from_name_map(arm); - if (ob->proxy) { /* sync proxy layer */ if (pose->proxy_layer) { @@ -3774,7 +3771,7 @@ static void lib_link_pose(FileData *fd, Main *bmain, Object *ob, bPose *pose) /* sync proxy active bone */ if (pose->proxy_act_bone[0]) { - Bone *bone = BLI_ghash_lookup(bone_hash, pose->proxy_act_bone); + Bone *bone = BKE_armature_find_bone_name(arm, pose->proxy_act_bone); if (bone) { arm->act_bone = bone; } @@ -3784,7 +3781,7 @@ static void lib_link_pose(FileData *fd, Main *bmain, Object *ob, bPose *pose) for (bPoseChannel *pchan = pose->chanbase.first; pchan; pchan = pchan->next) { lib_link_constraints(fd, (ID *)ob, &pchan->constraints); - pchan->bone = BLI_ghash_lookup(bone_hash, pchan->name); + pchan->bone = BKE_armature_find_bone_name(arm, pchan->name); IDP_LibLinkProperty(pchan->prop, fd); @@ -3799,8 +3796,6 @@ static void lib_link_pose(FileData *fd, Main *bmain, Object *ob, bPose *pose) } } - BLI_ghash_free(bone_hash, NULL, NULL); - if (rebuild) { DEG_id_tag_update_ex( bmain, &ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION); @@ -3858,6 +3853,7 @@ static void direct_link_armature(FileData *fd, bArmature *arm) Bone *bone; link_list(fd, &arm->bonebase); + arm->bonehash = NULL; arm->edbo = NULL; arm->adt = newdataadr(fd, arm->adt); @@ -3869,6 +3865,8 @@ static void direct_link_armature(FileData *fd, bArmature *arm) arm->act_bone = newdataadr(fd, arm->act_bone); arm->act_edbone = NULL; + + BKE_armature_bone_hash_make(arm); } /** \} */ diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c index 083967d5d41..9a1582679a4 100644 --- a/source/blender/editors/armature/armature_naming.c +++ b/source/blender/editors/armature/armature_naming.c @@ -180,7 +180,17 @@ void ED_armature_bone_rename(Main *bmain, if (bone) { unique_bone_name(arm, newname); + + if (arm->bonehash) { + BLI_assert(BLI_ghash_haskey(arm->bonehash, bone->name)); + BLI_ghash_remove(arm->bonehash, bone->name, NULL, NULL); + } + BLI_strncpy(bone->name, newname, MAXBONENAME); + + if (arm->bonehash) { + BLI_ghash_insert(arm->bonehash, bone->name, bone); + } } else { return; diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c index b23081cd6fa..20dc7b6c826 100644 --- a/source/blender/editors/armature/armature_utils.c +++ b/source/blender/editors/armature/armature_utils.c @@ -650,6 +650,7 @@ void ED_armature_from_edit(Main *bmain, bArmature *arm) Object *obt; /* armature bones */ + BKE_armature_bone_hash_free(arm); BKE_armature_bonelist_free(&arm->bonebase); arm->act_bone = NULL; @@ -754,6 +755,8 @@ void ED_armature_from_edit(Main *bmain, bArmature *arm) /* Finalize definition of restpose data (roll, bone_mat, arm_mat, head/tail...). */ armature_finalize_restpose(&arm->bonebase, arm->edbo); + BKE_armature_bone_hash_make(arm); + /* so all users of this armature should get rebuilt */ for (obt = bmain->objects.first; obt; obt = obt->id.next) { if (obt->data == arm) { diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h index 8ae9aa5a041..b18ab503e94 100644 --- a/source/blender/makesdna/DNA_armature_types.h +++ b/source/blender/makesdna/DNA_armature_types.h @@ -104,7 +104,11 @@ typedef struct bArmature { struct AnimData *adt; ListBase bonebase; - ListBase chainbase; + + /** Ghash for quicker lookups of bones by name. */ + struct GHash *bonehash; + void *_pad1; + /** Editbone listbase, we use pointer so we can check state. */ ListBase *edbo; diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c index d1e3cb1c860..ffd28b4eb76 100644 --- a/source/blender/makesrna/intern/rna_armature.c +++ b/source/blender/makesrna/intern/rna_armature.c @@ -575,6 +575,20 @@ static void rna_Armature_bones_next(CollectionPropertyIterator *iter) iter->valid = (internal->link != NULL); } +/* not essential, but much faster then the default lookup function */ +static int rna_Armature_bones_lookup_string(PointerRNA *ptr, const char *key, PointerRNA *r_ptr) +{ + bArmature *arm = (bArmature *)ptr->data; + Bone *bone = BKE_armature_find_bone_name(arm, key); + if (bone) { + RNA_pointer_create(ptr->id.data, &RNA_Bone, bone, r_ptr); + return true; + } + else { + return false; + } +} + static bool rna_Armature_is_editmode_get(PointerRNA *ptr) { bArmature *arm = (bArmature *)ptr->id.data; @@ -1285,8 +1299,15 @@ static void rna_def_armature(BlenderRNA *brna) /* Collections */ prop = RNA_def_property(srna, "bones", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "bonebase", NULL); - RNA_def_property_collection_funcs( - prop, NULL, "rna_Armature_bones_next", NULL, NULL, NULL, NULL, NULL, NULL); + RNA_def_property_collection_funcs(prop, + NULL, + "rna_Armature_bones_next", + NULL, + NULL, + NULL, + NULL, + "rna_Armature_bones_lookup_string", + NULL); RNA_def_property_struct_type(prop, "Bone"); RNA_def_property_ui_text(prop, "Bones", ""); rna_def_armature_bones(brna, prop); |