From 97b6948181df4ee97296ec45aebc75f31b7c790a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 8 Oct 2015 20:29:49 +1100 Subject: [PATCH] Fix T46386: Duplicate fails updating driver links Duplicate wasn't updating links, so duplicatinvg a objects would still point to the originals for curve-taper, texmesh, drivers. Use generic id-looper to handle replacing data. --- source/blender/blenkernel/BKE_library.h | 1 + source/blender/blenkernel/BKE_library_query.h | 1 + source/blender/blenkernel/BKE_object.h | 1 + source/blender/blenkernel/intern/library.c | 26 ++++++ .../blender/blenkernel/intern/library_query.c | 17 ++++ source/blender/blenkernel/intern/object.c | 32 ------- source/blender/editors/object/object_add.c | 85 ++----------------- .../blender/editors/object/object_relations.c | 2 +- 8 files changed, 53 insertions(+), 112 deletions(-) diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index 5b12858fc7d..4fab910b7ee 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -54,6 +54,7 @@ void *BKE_libblock_copy_ex(struct Main *bmain, struct ID *id) ATTR_WARN_UNUSED_R void *BKE_libblock_copy_nolib(struct ID *id, const bool do_action) ATTR_NONNULL(); void *BKE_libblock_copy(struct ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); void BKE_libblock_copy_data(struct ID *id, const struct ID *id_from, const bool do_action); +void BKE_libblock_relink(struct ID *id); void BKE_id_lib_local_paths(struct Main *bmain, struct Library *lib, struct ID *id); void id_lib_extern(struct ID *id); diff --git a/source/blender/blenkernel/BKE_library_query.h b/source/blender/blenkernel/BKE_library_query.h index 9daf16268c8..194b6f0e6b3 100644 --- a/source/blender/blenkernel/BKE_library_query.h +++ b/source/blender/blenkernel/BKE_library_query.h @@ -63,5 +63,6 @@ enum { /* Loop over all of the ID's this datablock links to. */ void BKE_library_foreach_ID_link(struct ID *id, LibraryIDLinkCallback callback, void *user_data, int flag); +void BKE_library_update_ID_link_user(struct ID *id_dst, struct ID *id_src, const int cd_flag); #endif /* __BKE_LIBRARY_QUERY_H__ */ diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 6c5081d1ea9..f3a1be24af6 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -234,6 +234,7 @@ int BKE_object_is_modified(struct Scene *scene, struct Object *ob); int BKE_object_is_deform_modified(struct Scene *scene, struct Object *ob); void BKE_object_relink(struct Object *ob); +void BKE_object_data_relink(struct Object *ob); struct MovieClip *BKE_object_movieclip_get(struct Scene *scene, struct Object *ob, bool use_default); diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 9fb0cb42dfc..d6b2a3cea29 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -95,6 +95,7 @@ #include "BKE_lamp.h" #include "BKE_lattice.h" #include "BKE_library.h" +#include "BKE_library_query.h" #include "BKE_linestyle.h" #include "BKE_mesh.h" #include "BKE_material.h" @@ -864,6 +865,31 @@ void *BKE_libblock_copy(ID *id) return BKE_libblock_copy_ex(G.main, id); } +static bool id_relink_looper(void *UNUSED(user_data), ID **id_pointer, const int cd_flag) +{ + ID *id = *id_pointer; + if (id) { + /* See: NEW_ID macro */ + if (id->newid) { + BKE_library_update_ID_link_user(id->newid, id, cd_flag); + *id_pointer = id->newid; + } + else if (id->flag & LIB_NEW) { + id->flag &= ~LIB_NEW; + BKE_libblock_relink(id); + } + } + return true; +} + +void BKE_libblock_relink(ID *id) +{ + if (id->lib) + return; + + BKE_library_foreach_ID_link(id, id_relink_looper, NULL, 0); +} + static void BKE_library_free(Library *lib) { if (lib->packedfile) diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c index 4e78c7b5049..b59d0cf5b6d 100644 --- a/source/blender/blenkernel/intern/library_query.c +++ b/source/blender/blenkernel/intern/library_query.c @@ -62,6 +62,7 @@ #include "BKE_animsys.h" #include "BKE_constraint.h" #include "BKE_fcurve.h" +#include "BKE_library.h" #include "BKE_library_query.h" #include "BKE_modifier.h" #include "BKE_particle.h" @@ -534,3 +535,19 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u #undef FOREACH_CALLBACK_INVOKE_ID #undef FOREACH_CALLBACK_INVOKE + +/** + * re-usable function, use when replacing ID's + */ +void BKE_library_update_ID_link_user(ID *id_dst, ID *id_src, const int cd_flag) +{ + if (cd_flag & IDWALK_USER) { + id_us_min(id_src); + id_us_plus(id_dst); + } + else if (cd_flag & IDWALK_USER_ONE) { + if (id_dst->us == 0) { + id_us_plus(id_dst); + } + } +} \ No newline at end of file diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 0c9239e3ddf..fb4b0a99d0a 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -3722,38 +3722,6 @@ bool BKE_object_is_animated(Scene *scene, Object *ob) return false; } -static void copy_object__forwardModifierLinks(void *UNUSED(userData), Object *UNUSED(ob), ID **idpoin) -{ - /* this is copied from ID_NEW; it might be better to have a macro */ - if (*idpoin && (*idpoin)->newid) *idpoin = (*idpoin)->newid; -} - -void BKE_object_relink(Object *ob) -{ - if (ob->id.lib) - return; - - BKE_constraints_relink(&ob->constraints); - if (ob->pose) { - bPoseChannel *chan; - for (chan = ob->pose->chanbase.first; chan; chan = chan->next) { - BKE_constraints_relink(&chan->constraints); - } - } - modifiers_foreachIDLink(ob, copy_object__forwardModifierLinks, NULL); - - if (ob->adt) - BKE_animdata_relink(ob->adt); - - if (ob->rigidbody_constraint) - BKE_rigidbody_relink_constraint(ob->rigidbody_constraint); - - ID_NEW(ob->parent); - - ID_NEW(ob->proxy); - ID_NEW(ob->proxy_group); -} - MovieClip *BKE_object_movieclip_get(Scene *scene, Object *ob, bool use_default) { MovieClip *clip = use_default ? scene->clip : NULL; diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index a5dc2d9970d..269700c3aef 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -1195,89 +1195,16 @@ void OBJECT_OT_delete(wmOperatorType *ot) /**************************** Copy Utilities ******************************/ /* after copying objects, copied data should get new pointers */ -static void copy_object_set_idnew(bContext *C, int dupflag) +static void copy_object_set_idnew(bContext *C) { Main *bmain = CTX_data_main(C); - Material *ma, *mao; - ID *id; - int a; - /* XXX check object pointers */ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) { - BKE_object_relink(ob); + BKE_libblock_relink(&ob->id); } CTX_DATA_END; - /* materials */ - if (dupflag & USER_DUP_MAT) { - mao = bmain->mat.first; - while (mao) { - if (mao->id.newid) { - ma = (Material *)mao->id.newid; - - if (dupflag & USER_DUP_TEX) { - for (a = 0; a < MAX_MTEX; a++) { - if (ma->mtex[a]) { - id = (ID *)ma->mtex[a]->tex; - if (id) { - ID_NEW_US(ma->mtex[a]->tex) - else - ma->mtex[a]->tex = BKE_texture_copy(ma->mtex[a]->tex); - id->us--; - } - } - } - } -#if 0 // XXX old animation system - id = (ID *)ma->ipo; - if (id) { - ID_NEW_US(ma->ipo) - else - ma->ipo = copy_ipo(ma->ipo); - id->us--; - } -#endif // XXX old animation system - } - mao = mao->id.next; - } - } - -#if 0 // XXX old animation system - /* lamps */ - if (dupflag & USER_DUP_IPO) { - Lamp *la = bmain->lamp.first; - while (la) { - if (la->id.newid) { - Lamp *lan = (Lamp *)la->id.newid; - id = (ID *)lan->ipo; - if (id) { - ID_NEW_US(lan->ipo) - else - lan->ipo = copy_ipo(lan->ipo); - id->us--; - } - } - la = la->id.next; - } - } - - /* ipos */ - ipo = bmain->ipo.first; - while (ipo) { - if (ipo->id.lib == NULL && ipo->id.newid) { - Ipo *ipon = (Ipo *)ipo->id.newid; - IpoCurve *icu; - for (icu = ipon->curve.first; icu; icu = icu->next) { - if (icu->driver) { - ID_NEW(icu->driver->ob); - } - } - } - ipo = ipo->id.next; - } -#endif // XXX old animation system - set_sca_new_poins(); BKE_main_id_clear_newpoins(bmain); @@ -1468,7 +1395,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, if (parent_gh) BLI_ghash_free(parent_gh, NULL, NULL); - copy_object_set_idnew(C, 0); + copy_object_set_idnew(C); free_object_duplilist(lb); @@ -2187,7 +2114,7 @@ Base *ED_object_add_duplicate(Main *bmain, Scene *scene, Base *base, int dupflag ob = basen->object; /* link own references to the newly duplicated data [#26816] */ - BKE_object_relink(ob); + BKE_libblock_relink(&ob->id); set_sca_new_poins_ob(ob); /* DAG_relations_tag_update(bmain); */ /* caller must do */ @@ -2232,7 +2159,7 @@ static int duplicate_exec(bContext *C, wmOperator *op) } CTX_DATA_END; - copy_object_set_idnew(C, dupflag); + copy_object_set_idnew(C); DAG_relations_tag_update(bmain); @@ -2317,7 +2244,7 @@ static int add_named_exec(bContext *C, wmOperator *op) ED_base_object_select(basen, BA_SELECT); ED_base_object_activate(C, basen); - copy_object_set_idnew(C, dupflag); + copy_object_set_idnew(C); DAG_relations_tag_update(bmain); diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index e21f58d8a38..3d030f1a770 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -1794,7 +1794,7 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in /* object and group pointers */ for (base = FIRSTBASE; base; base = base->next) { - BKE_object_relink(base->object); + BKE_libblock_relink(&base->object->id); } set_sca_new_poins();