Proxy appending: re-establish link to proxies when they are made local

This allows appending of an entire scene from another blend file into this one,
even when that blend file contains proxified armatures.

This replaces the approach from commit 1cdc54dc7d.

Thanks @sergey for the help.
This commit is contained in:
Sybren A. Stüvel 2016-10-13 13:32:08 +02:00
parent 918e6cf4c9
commit 5c651554e2
3 changed files with 23 additions and 41 deletions

View File

@ -108,6 +108,7 @@ struct Object *BKE_object_lod_matob_get(struct Object *ob, struct Scene *scene);
struct Object *BKE_object_copy_ex(struct Main *bmain, struct Object *ob, bool copy_caches);
struct Object *BKE_object_copy(struct Main *bmain, struct Object *ob);
void BKE_object_make_local(struct Main *bmain, struct Object *ob, const bool lib_local);
void BKE_object_make_local_ex(struct Main *bmain, struct Object *ob, const bool lib_local, const bool clear_proxy);
bool BKE_object_is_libdata(struct Object *ob);
bool BKE_object_obdata_is_libdata(struct Object *ob);

View File

@ -1592,15 +1592,6 @@ void id_clear_lib_data_ex(Main *bmain, ID *id, const bool id_in_mainlist)
if ((key = BKE_key_from_id(id))) {
id_clear_lib_data_ex(bmain, &key->id, id_in_mainlist); /* sigh, why are keys in Main? */
}
if (GS(id->name) == ID_OB) {
Object *object = (Object *)id;
if (object->proxy_from != NULL) {
object->proxy_from->proxy = NULL;
object->proxy_from->proxy_group = NULL;
}
object->proxy = object->proxy_from = object->proxy_group = NULL;
}
}
void id_clear_lib_data(Main *bmain, ID *id)
@ -1675,7 +1666,15 @@ void BKE_library_make_local(Main *bmain, const Library *lib, const bool untagged
if (lib == NULL || id->lib == lib) {
if (id->lib) {
/* In this specific case, we do want to make ID local even if it has no local usage yet... */
id_make_local(bmain, id, false, true);
if (GS(id->name) == ID_OB) {
/* Special case for objects because we don't want proxy pointers to be
* cleared yet. This will happen down the road in this function.
*/
BKE_object_make_local_ex(bmain, (Object*)id, true, false);
}
else {
id_make_local(bmain, id, false, true);
}
}
else {
id->tag &= ~(LIB_TAG_EXTERN | LIB_TAG_INDIRECT | LIB_TAG_NEW);
@ -1715,36 +1714,6 @@ void BKE_library_make_local(Main *bmain, const Library *lib, const bool untagged
bool is_local = false, is_lib = false;
BKE_library_ID_test_usages(bmain, id, &is_local, &is_lib);
/* Attempt to re-link appended proxy objects. This allows appending of an entire scene
* from another blend file into this one, even when that blend file contains proxified
* armatures. Since the proxified object needs to be linked (not local), this will
* only work when the "Localize all" checkbox is disabled.
* TL;DR: this is a dirty hack on top of an already weak feature (proxies). */
if (GS(id->name) == ID_OB && ((Object *)id)->proxy != NULL) {
Object *ob = (Object *)id;
Object *ob_new = (Object *)id->newid;
/* Proxies only work when the proxified object is linked-in from a library. */
if (ob->proxy->id.lib == NULL) {
printf("Warning, proxy object %s will loose its link to %s, because the "
"proxified object is local.\n", id->newid->name, ob->proxy->id.name);
}
/* We can only switch the proxy'ing to a made-local proxy if it is no longer
* referred to from a library. Not checking for local use; if new local proxy
* was not used locally would be a nasty bug! */
else if (is_local || is_lib) {
printf("Warning, made-local proxy object %s will loose its link to %s, "
"because the linked-in proxy is referenced (is_local=%i, is_lib=%i).\n",
id->newid->name, ob->proxy->id.name, is_local, is_lib);
}
else {
/* we can switch the proxy'ing from the linked-in to the made-local proxy. */
BKE_object_make_proxy(ob_new, ob->proxy, ob->proxy_group);
ob->proxy = ob->proxy_from = ob->proxy_group = NULL;
}
}
if (!is_local && !is_lib) {
BKE_libblock_free(bmain, id);
do_loop = true;

View File

@ -1181,7 +1181,7 @@ Object *BKE_object_copy(Main *bmain, Object *ob)
return BKE_object_copy_ex(bmain, ob, false);
}
void BKE_object_make_local(Main *bmain, Object *ob, const bool lib_local)
void BKE_object_make_local_ex(Main *bmain, Object *ob, const bool lib_local, const bool clear_proxy)
{
bool is_local = false, is_lib = false;
@ -1201,6 +1201,13 @@ void BKE_object_make_local(Main *bmain, Object *ob, const bool lib_local)
if (!is_lib) {
id_clear_lib_data(bmain, &ob->id);
BKE_id_expand_local(&ob->id);
if (clear_proxy) {
if (ob->proxy_from != NULL) {
ob->proxy_from->proxy = NULL;
ob->proxy_from->proxy_group = NULL;
}
ob->proxy = ob->proxy_from = ob->proxy_group = NULL;
}
}
else {
Object *ob_new = BKE_object_copy(bmain, ob);
@ -1215,6 +1222,11 @@ void BKE_object_make_local(Main *bmain, Object *ob, const bool lib_local)
}
}
void BKE_object_make_local(Main *bmain, Object *ob, const bool lib_local)
{
BKE_object_make_local_ex(bmain, ob, lib_local, true);
}
/* Returns true if the Object is from an external blend file (libdata) */
bool BKE_object_is_libdata(Object *ob)
{