[Bf-blender-cvs] [ded1333] id-remap: Rework a bit IDRemap struct to separate input flags from output status, and fix issues with unlinking ParticleSettings.
Bastien Montagne
noreply at git.blender.org
Wed Nov 11 16:54:56 CET 2015
Commit: ded1333f3cb711135de18ae7413b4d622e75a142
Author: Bastien Montagne
Date: Wed Nov 11 16:52:15 2015 +0100
Branches: id-remap
https://developer.blender.org/rBded1333f3cb711135de18ae7413b4d622e75a142
Rework a bit IDRemap struct to separate input flags from output status, and fix
issues with unlinking ParticleSettings.
We now have the option to still decrement user count of old_id, even if we could not
replace it with NULL new_id (aka unlinking), needed to keep proper user count when
unlinking and ID from datablocks it uses, to delete it.
===================================================================
M source/blender/blenkernel/BKE_library.h
M source/blender/blenkernel/intern/library.c
M source/blender/blenkernel/intern/particle.c
M source/blender/editors/render/render_preview.c
===================================================================
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index 5b8f741..6384143 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -66,7 +66,7 @@ void BKE_libblock_remap(
void BKE_libblock_unlink(struct Main *bmain, void *idv) ATTR_NONNULL();
-void BKE_libblock_relink_ex(void *idv, void *old_idv, void *new_idv) ATTR_NONNULL(1);
+void BKE_libblock_relink_ex(void *idv, void *old_idv, void *new_idv, const bool us_min_never_null) ATTR_NONNULL(1);
void BKE_id_lib_local_paths(struct Main *bmain, struct Library *lib, struct ID *id);
void id_lib_extern(struct ID *id);
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 9f6f2d3..377cd03 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -1027,20 +1027,31 @@ typedef struct IDRemap {
ID *old_id;
ID *new_id;
ID *id; /* The ID in which we are replacing old_id by new_id usages. */
- int flag;
+ short flag;
+ /* 'Output' data. */
+ short status;
int skipped_direct; /* Number of direct usecases that could not be remapped (e.g.: obdata when in edit mode). */
int skipped_indirect; /* Number of indirect usecases that could not be remapped. */
int skipped_refcounted; /* Number of skipped usecases that refcount the datablock. */
} IDRemap;
+/* IDRemp->flag */
enum {
- /* Set by caller. */
- ID_REMAP_SKIP_INDIRECT_USAGE = 1 << 0,
+ /* Do not remap indirect usages of IDs (that is, when user is some linked data). */
+ ID_REMAP_SKIP_INDIRECT_USAGE = 1 << 0,
+ /* This flag should always be set, *except for 'unlink' scenarios* (only relevant when new_id == NULL).
+ * Basically, when unset, NEVER_NULL ID usages will keep pointing to old_id, but (if needed) old_id user count
+ * will still be decremented. This is mandatory for 'delete ID' case, but in all other situation this would lead
+ * to invalid user counts! */
+ ID_REMAP_SKIP_NEVER_NULL_USAGE = 1 << 1,
+};
- /* Set by callback. */
- ID_REMAP_IS_LINKED_DIRECT = 1 << 16, /* new_id is directly linked in current .blend. */
- ID_REMAP_IS_USER_ONE_SKIPPED = 1 << 17, /* there was some skipped 'user_one' usages of old_id. */
+/* IDRemp->status */
+enum {
+ /* *** Set by callback. *** */
+ ID_REMAP_IS_LINKED_DIRECT = 1 << 0, /* new_id is directly linked in current .blend. */
+ ID_REMAP_IS_USER_ONE_SKIPPED = 1 << 1, /* There was some skipped 'user_one' usages of old_id. */
};
static bool foreach_libblock_remap_callback(void *user_data, ID **id_p, int cb_flag)
@@ -1065,12 +1076,13 @@ static bool foreach_libblock_remap_callback(void *user_data, ID **id_p, int cb_f
const bool is_indirect = (id->lib != NULL);
const bool skip_indirect = (id_remap_data->flag & ID_REMAP_SKIP_INDIRECT_USAGE) != 0;
const bool is_never_null = ((cb_flag & IDWALK_NEVER_NULL) && (new_id == NULL));
+ const bool skip_never_null = (id_remap_data->flag & ID_REMAP_SKIP_NEVER_NULL_USAGE) != 0;
printf("\t\tIn %s (%p): remapping %s (%p) to %s (%p)\n",
id->name, id, old_id->name, old_id, new_id ? new_id->name : "", new_id);
/* Special hack in case it's Object->data and we are in edit mode (skipped_direct too). */
- if (is_never_null ||
+ if ((is_never_null && skip_never_null) ||
(is_obj_editmode && (((Object *)id)->data == *id_p)) ||
(skip_indirect && (is_proxy || is_indirect)))
{
@@ -1085,11 +1097,13 @@ static bool foreach_libblock_remap_callback(void *user_data, ID **id_p, int cb_f
}
else if (cb_flag & IDWALK_USER_ONE) {
/* No need to count number of times this happens, just a flag is enough. */
- id_remap_data->flag |= ID_REMAP_IS_USER_ONE_SKIPPED;
+ id_remap_data->status |= ID_REMAP_IS_USER_ONE_SKIPPED;
}
}
else {
- *id_p = new_id;
+ if (!is_never_null) {
+ *id_p = new_id;
+ }
if (cb_flag & IDWALK_USER) {
id_us_min(old_id);
/* We do not want to handle LIB_INDIRECT/LIB_EXTERN here. */
@@ -1102,7 +1116,7 @@ static bool foreach_libblock_remap_callback(void *user_data, ID **id_p, int cb_f
* that extra user is processed in final handling... */
}
if (!is_indirect) {
- id_remap_data->flag |= ID_REMAP_IS_LINKED_DIRECT;
+ id_remap_data->status |= ID_REMAP_IS_LINKED_DIRECT;
}
}
}
@@ -1131,7 +1145,7 @@ static bool foreach_libblock_remap_callback(void *user_data, ID **id_p, int cb_f
* \return true is there was some 'user_one' users of \a old_id (needed to handle correctly #old_id->us count).
*/
static void libblock_remap_data(
- Main *bmain, ID *id, ID *old_id, ID *new_id, const bool skip_indirect_usage, IDRemap *r_id_remap_data)
+ Main *bmain, ID *id, ID *old_id, ID *new_id, const short remap_flags, IDRemap *r_id_remap_data)
{
IDRemap id_remap_data;
ListBase *lb_array[MAX_LIBARRAY];
@@ -1143,7 +1157,8 @@ static void libblock_remap_data(
r_id_remap_data->old_id = old_id;
r_id_remap_data->new_id = new_id;
r_id_remap_data->id = NULL;
- r_id_remap_data->flag = skip_indirect_usage ? ID_REMAP_SKIP_INDIRECT_USAGE : 0;
+ r_id_remap_data->flag = remap_flags;
+ r_id_remap_data->status = 0;
r_id_remap_data->skipped_direct = 0;
r_id_remap_data->skipped_indirect = 0;
r_id_remap_data->skipped_refcounted = 0;
@@ -1183,7 +1198,7 @@ static void libblock_remap_data(
id_fake_user_set(new_id);
}
- if (new_id && (new_id->flag & LIB_INDIRECT) && (r_id_remap_data->flag & ID_REMAP_IS_LINKED_DIRECT)) {
+ if (new_id && (new_id->flag & LIB_INDIRECT) && (r_id_remap_data->status & ID_REMAP_IS_LINKED_DIRECT)) {
new_id->flag &= ~LIB_INDIRECT;
new_id->flag |= LIB_EXTERN;
}
@@ -1199,6 +1214,7 @@ void BKE_libblock_remap_locked(Main *bmain, void *old_idv, void *new_idv, const
IDRemap id_remap_data;
ID *old_id = old_idv;
ID *new_id = new_idv;
+ int remap_flags = skip_indirect_usage ? ID_REMAP_SKIP_INDIRECT_USAGE : 0;
int skipped_direct, skipped_refcounted;
BLI_assert(old_id != NULL);
@@ -1207,7 +1223,7 @@ void BKE_libblock_remap_locked(Main *bmain, void *old_idv, void *new_idv, const
printf("%s: %s (%p) replaced by %s (%p)\n", __func__, old_id->name, old_id, new_id ? new_id->name : "", new_id);
- libblock_remap_data(bmain, NULL, old_id, new_id, skip_indirect_usage, &id_remap_data);
+ libblock_remap_data(bmain, NULL, old_id, new_id, remap_flags, &id_remap_data);
if (free_notifier_reference_cb) {
free_notifier_reference_cb(old_id);
@@ -1225,7 +1241,7 @@ void BKE_libblock_remap_locked(Main *bmain, void *old_idv, void *new_idv, const
/* If old_id was used by some ugly 'user_one' stuff (like Image or Clip editors...), and user count has actually
* been incremented for that, we have to decrease once more its user count... unless we had to skip
* some 'user_one' cases. */
- if ((old_id->flag2 & LIB_EXTRAUSER_SET) && !(id_remap_data.flag & ID_REMAP_IS_USER_ONE_SKIPPED)) {
+ if ((old_id->flag2 & LIB_EXTRAUSER_SET) && !(id_remap_data.status & ID_REMAP_IS_USER_ONE_SKIPPED)) {
id_us_min(old_id);
old_id->flag2 &= ~LIB_EXTRAUSER_SET;
}
@@ -1308,6 +1324,8 @@ void BKE_libblock_unlink(Main *bmain, void *idv)
/** Similar to libblock_remap, but only affects IDs used by given \a idv ID.
*
* \param old_id Unlike BKE_libblock_remap, can be NULL, in which case all ID usages by given \a idv will be cleared.
+ * \param us_min_never_null If true and new_id is NULL, 'NEVER_NULL' ID usages keep their old id, but this one still
+ * gets its user count decremented (needed when given \a idv is going to be deleted right after being unlinked).
*/
/* Should be able to replace all _relink() funcs (constraints, rigidbody, etc.) ? */
/* XXX Arg! Naming... :(
@@ -1317,11 +1335,12 @@ void BKE_libblock_unlink(Main *bmain, void *idv)
* BKE_id_remap maybe?
* ... sigh
*/
-void BKE_libblock_relink_ex(void *idv, void *old_idv, void *new_idv)
+void BKE_libblock_relink_ex(void *idv, void *old_idv, void *new_idv, const bool us_min_never_null)
{
ID *id = idv;
ID *old_id = old_idv;
ID *new_id = new_idv;
+ int remap_flags = us_min_never_null ? 0 : ID_REMAP_SKIP_NEVER_NULL_USAGE;
/* No need to lock here, we are only affecting given ID. */
@@ -1334,7 +1353,7 @@ void BKE_libblock_relink_ex(void *idv, void *old_idv, void *new_idv)
BLI_assert(new_id == NULL);
}
- libblock_remap_data(NULL, id, old_id, new_id, false, NULL);
+ libblock_remap_data(NULL, id, old_id, new_id, remap_flags, NULL);
}
static void animdata_dtar_clear_cb(ID *UNUSED(id), AnimData *adt, void *userdata)
@@ -1388,7 +1407,7 @@ void BKE_libblock_free_ex(Main *bmain, void *idv, bool do_id_user)
#endif
if (do_id_user) {
- BKE_libblock_relink_ex(id, NULL, NULL);
+ BKE_libblock_relink_ex(id, NULL, NULL, true);
}
switch (type) {
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index e76edf3..156fdd6 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -564,10 +564,7 @@ void psys_free(Object *ob, ParticleSystem *psys)
if (!nr)
ob->transflag &= ~OB_DUPLIPARTS;
- if (psys->part) {
- id_us_min(&psys->part->id);
- psys->part = NULL;
- }
+ psys->part = NULL;
BKE_ptcache_free_list(&psys->ptcaches);
psys->pointcache = NULL;
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index a647f6a..1751712 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -863,7 +863,7 @@ static void shader_preview_free(void *customdata)
/* get rid of copied world */
BLI_remlink(&pr_main->world, sp->worldcopy);
/* T32865 - we need to unlink the texture copies, unlike for materials */
- BKE_libblock_relink_ex(sp->worldcopy, NULL, NULL);
+ BKE_libblock_relink_ex(sp->worldcopy, NULL, NULL, true);
BKE_world_free(sp->worldcopy);
properties = IDP_GetProperties((ID *)sp->worldcopy, false);
@@ -880,7 +880,7 @@ static void shader_preview_free(void *customdata)
/* get rid of copied lamp */
BLI_remlink(&pr_main->lamp, sp->lampcopy);
- BKE_libblock_relink_ex(sp->lampcop
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list