From 252bfc6f65564185aa3b3b9849cc6c486f4c3e78 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 8 Dec 2014 16:13:27 +0100 Subject: [PATCH] Fix T42838: Make dupli's real use_hierarchy fails Regression since the dupli-object refactor. --- source/blender/editors/object/object_add.c | 57 +++++++++++++++++++--- 1 file changed, 50 insertions(+), 7 deletions(-) diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 0021f13e31b..63808704781 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -1286,6 +1286,44 @@ static void copy_object_set_idnew(bContext *C, int dupflag) /********************* Make Duplicates Real ************************/ +/** + * \note regarding hashing dupli-objects, skip the first member of #DupliObject.persistent_id + * since its a unique index and we only wan't to know if the group objects are from the same dupli-group instance. + */ +static unsigned int dupliobject_hash(const void *ptr) +{ + const DupliObject *dob = ptr; + unsigned int hash = BLI_ghashutil_ptrhash(dob->ob); + unsigned int i; + for (i = 1; (i < MAX_DUPLI_RECUR) && dob->persistent_id[i] != INT_MAX; i++) { + hash ^= (dob->persistent_id[i] ^ i); + } + return hash; +} + +static bool dupliobject_cmp(const void *a_, const void *b_) +{ + const DupliObject *a = a_; + const DupliObject *b = b_; + unsigned int i; + + if (a->ob != b->ob) { + return true; + } + + for (i = 1; (i < MAX_DUPLI_RECUR); i++) { + if (a->persistent_id[i] != b->persistent_id[i]) { + return true; + } + else if (a->persistent_id[i] == INT_MAX) { + break; + } + } + + /* matching */ + return false; +} + static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, const bool use_base_parent, const bool use_hierarchy) @@ -1302,8 +1340,8 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, lb = object_duplilist(bmain->eval_ctx, scene, base->object); if (use_hierarchy || use_base_parent) { - dupli_gh = BLI_ghash_ptr_new("make_object_duplilist_real dupli_gh"); - parent_gh = BLI_ghash_pair_new("make_object_duplilist_real parent_gh"); + dupli_gh = BLI_ghash_ptr_new(__func__); + parent_gh = BLI_ghash_new(dupliobject_hash, dupliobject_cmp, __func__); } for (dob = lb->first; dob; dob = dob->next) { @@ -1343,7 +1381,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, if (dupli_gh) BLI_ghash_insert(dupli_gh, dob, ob); if (parent_gh) - BLI_ghash_insert(parent_gh, BLI_ghashutil_pairalloc(dob->ob, SET_INT_IN_POINTER(dob->persistent_id[0])), ob); + BLI_ghash_insert(parent_gh, dob, ob); DAG_id_tag_update(&ob->id, OB_RECALC_DATA); } @@ -1359,9 +1397,14 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, /* find parent that was also made real */ if (ob_src_par) { - GHashPair *pair = BLI_ghashutil_pairalloc(ob_src_par, SET_INT_IN_POINTER(dob->persistent_id[0])); - ob_dst_par = BLI_ghash_lookup(parent_gh, pair); - BLI_ghashutil_pairfree(pair); + /* OK to keep most of the members uninitialized, + * they won't be read, this is simply for a hash lookup. */ + DupliObject dob_key; + dob_key.ob = ob_src_par; + memcpy(&dob_key.persistent_id[1], + &dob->persistent_id[1], + sizeof(dob->persistent_id[1]) * (MAX_DUPLI_RECUR - 1)); + ob_dst_par = BLI_ghash_lookup(parent_gh, &dob_key); } if (ob_dst_par) { @@ -1424,7 +1467,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, if (dupli_gh) BLI_ghash_free(dupli_gh, NULL, NULL); if (parent_gh) - BLI_ghash_free(parent_gh, BLI_ghashutil_pairfree, NULL); + BLI_ghash_free(parent_gh, NULL, NULL); copy_object_set_idnew(C, 0);