From 00166ff62e689b7caebdd3a0c4f9051b2739826a Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 14 Mar 2016 15:05:52 +0100 Subject: Better fix for T47787 - remove extra user due to 'user_one' as soon as we increase 'real' user count. This has several benefits: * User count remains coherent, regardless of the order in which you use 'user_one' & real refcounting users (i.e. if you add to group, and then link in scene, or the reverse, you now always get same final user count). * Avoids the need to check for potential 'user_one' extra user in count in several places in code (e.g. when making IDs single users...). * Users won't wonder why they cannot make 'single user' and ID even though its user count shows '2'! * readfile.c now always uses code from BKE's library.c when modifying id->us. Which means we can consider (asside from assignment during initialization) that id->us is read-only outside of library.c context. Note that this commit reverts previous one (rB6b1d77a8052b) - please **do not** backport this one in 2.77. --- source/blender/blenkernel/BKE_library.h | 1 + source/blender/blenkernel/intern/library.c | 22 ++++++++++++++++++++-- source/blender/blenloader/intern/readfile.c | 11 +++++------ source/blender/editors/object/object_relations.c | 2 +- source/blender/makesdna/DNA_ID.h | 1 - 5 files changed, 27 insertions(+), 10 deletions(-) diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index 606edd9cc3a..21585a160dd 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -73,6 +73,7 @@ void id_lib_extern(struct ID *id); void BKE_library_filepath_set(struct Library *lib, const char *filepath); void id_us_ensure_real(struct ID *id); void id_us_clear_real(struct ID *id); +void id_us_plus_no_lib(struct ID *id); void id_us_plus(struct ID *id); void id_us_min(struct ID *id); void id_fake_user_set(struct ID *id); diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index c04eda00904..6d7a61534a8 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -194,11 +194,29 @@ void id_us_clear_real(ID *id) } } +/* Same as \a id_us_plus, but does not handle lib indirect -> extern. + * Only used by readfile.c so far, but simpler/safer to keep it here nontheless. */ +void id_us_plus_no_lib(ID *id) +{ + if (id) { + if ((id->tag & LIB_TAG_EXTRAUSER) && (id->tag & LIB_TAG_EXTRAUSER_SET)) { + BLI_assert(id->us >= 1); + /* No need to increase count, just tag extra user as no more set. + * Avoids annoying & inconsistent +1 in user count. */ + id->tag &= ~LIB_TAG_EXTRAUSER_SET; + } + else { + BLI_assert(id->us >= 0); + id->us++; + } + } +} + + void id_us_plus(ID *id) { if (id) { - BLI_assert(id->us >= 0); - id->us++; + id_us_plus_no_lib(id); id_lib_extern(id); } } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 375837437d8..8b41c618c99 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -1497,8 +1497,7 @@ static void *newlibadr_us(FileData *fd, void *lib, void *adr) /* increases user { ID *id = newlibadr(fd, lib, adr); - if (id) - id->us++; + id_us_plus_no_lib(id); return id; } @@ -4640,7 +4639,7 @@ static void lib_link_modifiers__linkModifiers( *idpoin = newlibadr(fd, ob->id.lib, *idpoin); if (*idpoin != NULL && (cd_flag & IDWALK_USER) != 0) { - (*idpoin)->us++; + id_us_plus_no_lib(*idpoin); } } static void lib_link_modifiers(FileData *fd, Object *ob) @@ -5638,7 +5637,7 @@ static void lib_link_scene(FileData *fd, Main *main) seq->sound = newlibadr(fd, sce->id.lib, seq->sound); } if (seq->sound) { - seq->sound->id.us++; + id_us_plus_no_lib((ID *)seq->sound); seq->scene_sound = BKE_sound_add_scene_sound_defaults(sce, seq); } } @@ -9580,7 +9579,7 @@ static void give_base_to_objects(Main *mainvar, Scene *scene, View3D *v3d, Libra base->flag = ob->flag; CLAMP_MIN(ob->id.us, 0); - ob->id.us += 1; + id_us_plus_no_lib((ID *)ob); ob->id.tag &= ~LIB_TAG_INDIRECT; ob->id.tag |= LIB_TAG_EXTERN; @@ -9704,7 +9703,7 @@ static void link_object_postprocess(ID *id, Scene *scene, View3D *v3d, const sho base->lay = ob->lay; base->object = ob; base->flag = ob->flag; - ob->id.us++; + id_us_plus_no_lib((ID *)ob); if (flag & FILE_AUTOSELECT) { base->flag |= SELECT; diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 0422ac61c69..1a3209a8ca8 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -1749,7 +1749,7 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in ob = base->object; if ((base->flag & flag) == flag) { - if (ob->id.lib == NULL && ID_REFCOUNT_USERS(ob) > 1) { + if (ob->id.lib == NULL && ob->id.us > 1) { /* base gets copy of object */ obn = BKE_object_copy(ob); base->object = obn; diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index eff68521b76..0bf3c350263 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -260,7 +260,6 @@ typedef struct PreviewImage { #define ID_FAKE_USERS(id) ((((ID *)id)->flag & LIB_FAKEUSER) ? 1 : 0) #define ID_REAL_USERS(id) (((ID *)id)->us - ID_FAKE_USERS(id)) -#define ID_REFCOUNT_USERS(id) (((ID *)id)->us - ((((ID *)id)->tag & LIB_TAG_EXTRAUSER_SET) ? 1 : 0) - ID_FAKE_USERS(id)) #define ID_CHECK_UNDO(id) ((GS((id)->name) != ID_SCR) && (GS((id)->name) != ID_WM)) -- cgit v1.2.3