Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorBastien Montagne <montagne29@wanadoo.fr>2016-07-08 17:20:21 +0300
committerBastien Montagne <montagne29@wanadoo.fr>2016-07-08 19:11:20 +0300
commitd1a4ae3f395a6dbb6487c5885d2327129d9b4532 (patch)
tree7602507455f9be0963087904b379c44ec8f3c772 /source
parentf3fe1f9c44b08de6d18cad27d8751585568b7e8e (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.h2
-rw-r--r--source/blender/blenkernel/intern/library.c4
-rw-r--r--source/blender/blenkernel/intern/object.c79
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);
}
}
}