[Bf-blender-cvs] [26d2652d6d4] master: Armature: implement universal hash table lookup of Bone objects by name.

Alexander Gavrilov noreply at git.blender.org
Tue May 14 21:28:26 CEST 2019


Commit: 26d2652d6d4287801d56dc8d41b1037750af701a
Author: Alexander Gavrilov
Date:   Tue May 14 21:48:22 2019 +0300
Branches: master
https://developer.blender.org/rB26d2652d6d4287801d56dc8d41b1037750af701a

Armature: implement universal hash table lookup of Bone objects by name.

Since drivers on Bone properties are really supposed to be stored
in Armature data and access bones via its bones[] collection, this
lookup path should work efficiently.

Mass lookup of bones by name was already done through hashes,
but they were built temporarily every time that was needed. This
simply replaces it with a common hash table computed immediately
after file load, copy, or Edit to Object mode switch.

===================================================================

M	source/blender/blenkernel/BKE_armature.h
M	source/blender/blenkernel/intern/armature.c
M	source/blender/blenloader/intern/readfile.c
M	source/blender/editors/armature/armature_naming.c
M	source/blender/editors/armature/armature_utils.c
M	source/blender/makesdna/DNA_armature_types.h
M	source/blender/makesrna/intern/rna_armature.c

===================================================================

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)
 {
  

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list