diff options
author | Bastien Montagne <montagne29@wanadoo.fr> | 2016-07-08 17:20:21 +0300 |
---|---|---|
committer | Bastien Montagne <montagne29@wanadoo.fr> | 2016-07-08 19:11:20 +0300 |
commit | d1a4ae3f395a6dbb6487c5885d2327129d9b4532 (patch) | |
tree | 7602507455f9be0963087904b379c44ec8f3c772 /source | |
parent | f3fe1f9c44b08de6d18cad27d8751585568b7e8e (diff) |
Refactor/enhance BKE_object_make_local().
Now using modern features from libquery/libremap areas.
Also, it should handle much better cases where localized ID was also indirectly used by non-refcounting users
(typical case: object used as modifier/constraint/whatever target from another linked object, previous
code would not take those into account and just localize original object instead of making a local copy.
Would result in local object used by linked one, which would be partially 'undone' on next file reload... Crappy behavior).
And it fixes some obvious errors too (nullifying all proxy pointers unconditionnaly,
some missing refcounted usages cases in extern_local_object(), etc.).
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_object.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/library.c | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/object.c | 79 |
3 files changed, 25 insertions, 60 deletions
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index f46fb73f4c9..a1f1bee2642 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -107,7 +107,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 Object *ob); -void BKE_object_make_local(struct Object *ob); +void BKE_object_make_local(struct Main *bmain, struct Object *ob); bool BKE_object_is_libdata(struct Object *ob); bool BKE_object_obdata_is_libdata(struct Object *ob); diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 374afa64ca4..132dd1217b0 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -253,7 +253,7 @@ void id_fake_user_clear(ID *id) /* calls the appropriate make_local method for the block, unless test. Returns true * if the block can be made local. */ -bool id_make_local(Main *UNUSED(bmain), ID *id, bool test) +bool id_make_local(Main *bmain, ID *id, bool test) { if (id->tag & LIB_TAG_INDIRECT) return false; @@ -264,7 +264,7 @@ bool id_make_local(Main *UNUSED(bmain), ID *id, bool test) case ID_LI: return false; /* can't be linked */ case ID_OB: - if (!test) BKE_object_make_local((Object *)id); + if (!test) BKE_object_make_local(bmain, (Object *)id); return true; case ID_ME: if (!test) { diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 22ab232bf43..300dc73a24c 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -93,6 +93,8 @@ #include "BKE_lamp.h" #include "BKE_lattice.h" #include "BKE_library.h" +#include "BKE_library_query.h" +#include "BKE_library_remap.h" #include "BKE_linestyle.h" #include "BKE_mesh.h" #include "BKE_editmesh.h" @@ -1184,41 +1186,25 @@ Object *BKE_object_copy(Object *ob) return BKE_object_copy_ex(G.main, ob, false); } -static void extern_local_object__modifiersForeachIDLink( - void *UNUSED(userData), Object *UNUSED(ob), ID **idpoin, int UNUSED(cd_flag)) +static int extern_local_object_callback( + void *UNUSED(user_data), struct ID *UNUSED(id_self), struct ID **id_pointer, int cd_flag) { - if (*idpoin) { - /* intentionally omit ID_OB */ - if (ELEM(GS((*idpoin)->name), ID_IM, ID_TE)) { - id_lib_extern(*idpoin); - } + /* We only tag usercounted ID usages as extern... Why? */ + if ((cd_flag & IDWALK_USER) && *id_pointer) { + id_lib_extern(*id_pointer); } + return IDWALK_NOP; } static void extern_local_object(Object *ob) { - ParticleSystem *psys; - - id_lib_extern((ID *)ob->data); - id_lib_extern((ID *)ob->dup_group); - id_lib_extern((ID *)ob->poselib); - id_lib_extern((ID *)ob->gpd); - - extern_local_matarar(ob->mat, ob->totcol); - - for (psys = ob->particlesystem.first; psys; psys = psys->next) - id_lib_extern((ID *)psys->part); - - modifiers_foreachIDLink(ob, extern_local_object__modifiersForeachIDLink, NULL); + BKE_library_foreach_ID_link(&ob->id, extern_local_object_callback, NULL, 0); ob->preview = NULL; } -void BKE_object_make_local(Object *ob) +void BKE_object_make_local(Main *bmain, Object *ob) { - Main *bmain = G.main; - Scene *sce; - Base *base; bool is_local = false, is_lib = false; /* - only lib users: do nothing @@ -1226,49 +1212,28 @@ void BKE_object_make_local(Object *ob) * - mixed: make copy */ - if (!ID_IS_LINKED_DATABLOCK(ob)) return; - - ob->proxy = ob->proxy_from = ob->proxy_group = NULL; - - if (ob->id.us == 1) { - id_clear_lib_data(bmain, &ob->id); - extern_local_object(ob); + if (!ID_IS_LINKED_DATABLOCK(ob)) { + return; } - else { - for (sce = bmain->scene.first; sce && ELEM(0, is_lib, is_local); sce = sce->id.next) { - if (BKE_scene_base_find(sce, ob)) { - if (ID_IS_LINKED_DATABLOCK(sce)) is_lib = true; - else is_local = true; - } - } - if (is_local && is_lib == false) { + BKE_library_ID_test_usages(bmain, ob, &is_local, &is_lib); + + if (is_local) { + if (!is_lib) { + ob->proxy = ob->proxy_from = ob->proxy_group = NULL; id_clear_lib_data(bmain, &ob->id); extern_local_object(ob); } - else if (is_local && is_lib) { - Object *ob_new = BKE_object_copy(ob); + else { + Object *ob_new = BKE_object_copy_ex(bmain, ob, false); ob_new->id.us = 0; - + ob_new->proxy = ob_new->proxy_from = ob_new->proxy_group = NULL; + /* Remap paths of new ID using old library as base. */ BKE_id_lib_local_paths(bmain, ob->id.lib, &ob_new->id); - sce = bmain->scene.first; - while (sce) { - if (!ID_IS_LINKED_DATABLOCK(sce)) { - base = sce->base.first; - while (base) { - if (base->object == ob) { - base->object = ob_new; - id_us_plus(&ob_new->id); - id_us_min(&ob->id); - } - base = base->next; - } - } - sce = sce->id.next; - } + BKE_libblock_remap(bmain, ob, ob_new, ID_REMAP_SKIP_INDIRECT_USAGE); } } } |