forked from bartvdbraak/blender
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.
This commit is contained in:
parent
5eb500f2fc
commit
97b6948181
@ -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_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(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_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 BKE_id_lib_local_paths(struct Main *bmain, struct Library *lib, struct ID *id);
|
||||||
void id_lib_extern(struct ID *id);
|
void id_lib_extern(struct ID *id);
|
||||||
|
@ -63,5 +63,6 @@ enum {
|
|||||||
|
|
||||||
/* Loop over all of the ID's this datablock links to. */
|
/* 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_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__ */
|
#endif /* __BKE_LIBRARY_QUERY_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);
|
int BKE_object_is_deform_modified(struct Scene *scene, struct Object *ob);
|
||||||
|
|
||||||
void BKE_object_relink(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);
|
struct MovieClip *BKE_object_movieclip_get(struct Scene *scene, struct Object *ob, bool use_default);
|
||||||
|
|
||||||
|
@ -95,6 +95,7 @@
|
|||||||
#include "BKE_lamp.h"
|
#include "BKE_lamp.h"
|
||||||
#include "BKE_lattice.h"
|
#include "BKE_lattice.h"
|
||||||
#include "BKE_library.h"
|
#include "BKE_library.h"
|
||||||
|
#include "BKE_library_query.h"
|
||||||
#include "BKE_linestyle.h"
|
#include "BKE_linestyle.h"
|
||||||
#include "BKE_mesh.h"
|
#include "BKE_mesh.h"
|
||||||
#include "BKE_material.h"
|
#include "BKE_material.h"
|
||||||
@ -864,6 +865,31 @@ void *BKE_libblock_copy(ID *id)
|
|||||||
return BKE_libblock_copy_ex(G.main, 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)
|
static void BKE_library_free(Library *lib)
|
||||||
{
|
{
|
||||||
if (lib->packedfile)
|
if (lib->packedfile)
|
||||||
|
@ -62,6 +62,7 @@
|
|||||||
#include "BKE_animsys.h"
|
#include "BKE_animsys.h"
|
||||||
#include "BKE_constraint.h"
|
#include "BKE_constraint.h"
|
||||||
#include "BKE_fcurve.h"
|
#include "BKE_fcurve.h"
|
||||||
|
#include "BKE_library.h"
|
||||||
#include "BKE_library_query.h"
|
#include "BKE_library_query.h"
|
||||||
#include "BKE_modifier.h"
|
#include "BKE_modifier.h"
|
||||||
#include "BKE_particle.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_ID
|
||||||
#undef FOREACH_CALLBACK_INVOKE
|
#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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3722,38 +3722,6 @@ bool BKE_object_is_animated(Scene *scene, Object *ob)
|
|||||||
return false;
|
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 *BKE_object_movieclip_get(Scene *scene, Object *ob, bool use_default)
|
||||||
{
|
{
|
||||||
MovieClip *clip = use_default ? scene->clip : NULL;
|
MovieClip *clip = use_default ? scene->clip : NULL;
|
||||||
|
@ -1195,89 +1195,16 @@ void OBJECT_OT_delete(wmOperatorType *ot)
|
|||||||
/**************************** Copy Utilities ******************************/
|
/**************************** Copy Utilities ******************************/
|
||||||
|
|
||||||
/* after copying objects, copied data should get new pointers */
|
/* 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);
|
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)
|
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
|
||||||
{
|
{
|
||||||
BKE_object_relink(ob);
|
BKE_libblock_relink(&ob->id);
|
||||||
}
|
}
|
||||||
CTX_DATA_END;
|
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();
|
set_sca_new_poins();
|
||||||
|
|
||||||
BKE_main_id_clear_newpoins(bmain);
|
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)
|
if (parent_gh)
|
||||||
BLI_ghash_free(parent_gh, NULL, NULL);
|
BLI_ghash_free(parent_gh, NULL, NULL);
|
||||||
|
|
||||||
copy_object_set_idnew(C, 0);
|
copy_object_set_idnew(C);
|
||||||
|
|
||||||
free_object_duplilist(lb);
|
free_object_duplilist(lb);
|
||||||
|
|
||||||
@ -2187,7 +2114,7 @@ Base *ED_object_add_duplicate(Main *bmain, Scene *scene, Base *base, int dupflag
|
|||||||
ob = basen->object;
|
ob = basen->object;
|
||||||
|
|
||||||
/* link own references to the newly duplicated data [#26816] */
|
/* link own references to the newly duplicated data [#26816] */
|
||||||
BKE_object_relink(ob);
|
BKE_libblock_relink(&ob->id);
|
||||||
set_sca_new_poins_ob(ob);
|
set_sca_new_poins_ob(ob);
|
||||||
|
|
||||||
/* DAG_relations_tag_update(bmain); */ /* caller must do */
|
/* DAG_relations_tag_update(bmain); */ /* caller must do */
|
||||||
@ -2232,7 +2159,7 @@ static int duplicate_exec(bContext *C, wmOperator *op)
|
|||||||
}
|
}
|
||||||
CTX_DATA_END;
|
CTX_DATA_END;
|
||||||
|
|
||||||
copy_object_set_idnew(C, dupflag);
|
copy_object_set_idnew(C);
|
||||||
|
|
||||||
DAG_relations_tag_update(bmain);
|
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_select(basen, BA_SELECT);
|
||||||
ED_base_object_activate(C, basen);
|
ED_base_object_activate(C, basen);
|
||||||
|
|
||||||
copy_object_set_idnew(C, dupflag);
|
copy_object_set_idnew(C);
|
||||||
|
|
||||||
DAG_relations_tag_update(bmain);
|
DAG_relations_tag_update(bmain);
|
||||||
|
|
||||||
|
@ -1794,7 +1794,7 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
|
|||||||
|
|
||||||
/* object and group pointers */
|
/* object and group pointers */
|
||||||
for (base = FIRSTBASE; base; base = base->next) {
|
for (base = FIRSTBASE; base; base = base->next) {
|
||||||
BKE_object_relink(base->object);
|
BKE_libblock_relink(&base->object->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
set_sca_new_poins();
|
set_sca_new_poins();
|
||||||
|
Loading…
Reference in New Issue
Block a user