[Bf-blender-cvs] [9584c88] id-remap: Fix a bunch of more stuff, more correct handling of ID/Lib deletion...

Bastien Montagne noreply at git.blender.org
Thu Dec 3 16:36:52 CET 2015


Commit: 9584c88b6b482157eb6238f9690ea259c663b175
Author: Bastien Montagne
Date:   Tue Dec 1 21:37:25 2015 +0100
Branches: id-remap
https://developer.blender.org/rB9584c88b6b482157eb6238f9690ea259c663b175

Fix a bunch of more stuff, more correct handling of ID/Lib deletion...

Still have some usercount issues here, though things seems to start working...

===================================================================

M	source/blender/blenkernel/BKE_library.h
M	source/blender/blenkernel/intern/blender.c
M	source/blender/blenkernel/intern/library.c
M	source/blender/blenkernel/intern/library_query.c
M	source/blender/editors/object/object_group.c
M	source/blender/editors/screen/screen_edit.c
M	source/blender/editors/space_outliner/outliner_edit.c
M	source/blender/editors/space_outliner/outliner_tools.c
M	source/blender/makesrna/intern/rna_ID.c
M	source/blender/makesrna/intern/rna_main_api.c
M	source/blender/render/intern/source/pipeline.c
M	source/blender/windowmanager/intern/wm_operators.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index 8381394..fb9f443 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -60,11 +60,11 @@ void  BKE_libblock_relink(struct ID *id);
 
 /* Note: Requiring new_id to be non-null, this *may* not be the case ultimately, but makes things simpler for now. */
 void BKE_libblock_remap_locked(
-        struct Main *bmain, void *old_id, void *new_id, const bool skip_indirect_usage) ATTR_NONNULL(1, 2);
+        struct Main *bmain, void *old_idv, void *new_idv, const bool skip_indirect_usage, const bool do_flag_never_null) ATTR_NONNULL(1, 2);
 void BKE_libblock_remap(
-        struct Main *bmain, void *old_idv, void *new_idv, const bool skip_indirect_usage) ATTR_NONNULL(1, 2);
+        struct Main *bmain, void *old_idv, void *new_idv, const bool skip_indirect_usage, const bool do_flag_never_null) ATTR_NONNULL(1, 2);
 
-void BKE_libblock_unlink(struct Main *bmain, void *idv) ATTR_NONNULL();
+void BKE_libblock_unlink(struct Main *bmain, void *idv, const bool do_flag_never_null) ATTR_NONNULL();
 
 void BKE_libblock_relink_ex(void *idv, void *old_idv, void *new_idv, const bool us_min_never_null) ATTR_NONNULL(1);
 
@@ -91,10 +91,11 @@ struct ListBase *which_libbase(struct Main *mainlib, short type);
 int set_listbasepointers(struct Main *main, struct ListBase *lb[MAX_LIBARRAY]);
 
 void BKE_libblock_free(struct Main *bmain, void *idv);
-void BKE_libblock_free_ex(struct Main *bmain, void *idv, const bool do_id_user, const bool use_recursive_delete);
+void BKE_libblock_free_ex(struct Main *bmain, void *idv, const bool do_id_user);
 void BKE_libblock_free_us(struct Main *bmain, void *idv);
 void BKE_libblock_free_data(struct Main *bmain, struct ID *id);
 
+void BKE_libblock_delete(struct Main *bmain, void *idv) ATTR_NONNULL();
 
 /* Main API */
 struct Main *BKE_main_new(void);
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index 3288496..fc76c29 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -565,9 +565,9 @@ bool BKE_read_file_from_memfile(
 	if (bfd) {
 		/* remove the unused screens and wm */
 		while (bfd->main->wm.first)
-			BKE_libblock_free_ex(bfd->main, bfd->main->wm.first, true, false);
+			BKE_libblock_free_ex(bfd->main, bfd->main->wm.first, true);
 		while (bfd->main->screen.first)
-			BKE_libblock_free_ex(bfd->main, bfd->main->screen.first, true, false);
+			BKE_libblock_free_ex(bfd->main, bfd->main->screen.first, true);
 		
 		setup_app_data(C, bfd, "<memory1>");
 	}
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 614e351..a975a06 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -1044,6 +1044,9 @@ enum {
 	 * 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,
+	/* This tells the callback func to flag with LIB_DOIT all IDs using target one with a 'never NULL' pointer
+	 * (like e.g. Object->data). */
+	ID_REMAP_FLAG_NEVER_NULL_USAGE  = 1 << 2,
 };
 
 /* IDRemp->status */
@@ -1070,13 +1073,17 @@ static bool foreach_libblock_remap_callback(void *user_data, ID **id_p, int cb_f
 		 *       on the other hand since they get reset to lib data on file open/reload it is indirect too...
 		 *       Edit Mode is also a 'skip direct' case. */
 		const bool is_obj = (GS(id->name) == ID_OB);
-		const bool is_proxy = (is_obj && (((Object *)id)->proxy || ((Object *)id)->proxy_group));
+		const bool is_proxy = false; //(is_obj && (((Object *)id)->proxy || ((Object *)id)->proxy_group));
 		const bool is_obj_editmode = (is_obj && BKE_object_is_in_editmode((Object *)id));
 		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;
 
+		if ((id_remap_data->flag & ID_REMAP_FLAG_NEVER_NULL_USAGE) && (cb_flag & IDWALK_NEVER_NULL)) {
+			id->flag |= LIB_DOIT;
+		}
+
 //		if (GS(old_id->name) == ID_AC)
 //			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 : "<NONE>", new_id);
@@ -1211,19 +1218,50 @@ static void libblock_remap_data(
 //	       r_id_remap_data->skipped_direct, r_id_remap_data->skipped_indirect);
 }
 
-/** Replace all references in .blend file to \a old_id by \a new_id (if \a new_id is NULL, it unlinks \a old_id). */
-void BKE_libblock_remap_locked(Main *bmain, void *old_idv, void *new_idv, const bool skip_indirect_usage)
+/**
+ * Replace all references in given Main to \a old_id by \a new_id (if \a new_id is NULL, it unlinks \a old_id).
+ *
+ * \param skip_indirect_usage If \a true, indirect usages (like e.g. by other linked datablocks) are not remapped.
+ * \param do_flag_never_null If \a true, 'NEVER_NULL' ID users are flagged with LIB_DOIT (caller is expected
+ *                           to ensure that flag is correctly unset first).
+ */
+void BKE_libblock_remap_locked(
+        Main *bmain, void *old_idv, void *new_idv, const bool skip_indirect_usage, const bool do_flag_never_null)
 {
 	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 remap_flags = ((skip_indirect_usage ? ID_REMAP_SKIP_INDIRECT_USAGE : 0) |
+	                   (do_flag_never_null ? ID_REMAP_FLAG_NEVER_NULL_USAGE : 0));
 	int skipped_direct, skipped_refcounted;
 
 	BLI_assert(old_id != NULL);
 	BLI_assert((new_id == NULL) || GS(old_id->name) == GS(new_id->name));
 	BLI_assert(old_id != new_id);
 
+	/* Some pre-process updates.
+	 * This is a bit ugly, but cannot see a way to avoid it. Maybe we should do a per-ID callback for this instead?
+	 */
+	if (GS(old_id->name) == ID_OB) {
+		Object *old_ob = (Object *)old_id;
+		Object *new_ob = (Object *)new_id;
+
+		if (new_ob == NULL) {
+			Scene *sce;
+			Base *base;
+
+			for (sce = bmain->scene.first; sce; sce = sce->id.next) {
+				base = BKE_scene_base_find(sce, old_ob);
+
+				if (base) {
+					id_us_min((ID *)base->object);
+					BKE_scene_base_unlink(sce, base);
+					MEM_freeN(base);
+				}
+			}
+		}
+	}
+
 //	if (GS(old_id->name) == ID_AC) {
 //		printf("%s: START %s (%p, %d) replaced by %s (%p, %d)\n",
 //		       __func__, old_id->name, old_id, old_id->us, new_id ? new_id->name : "", new_id, new_id ? new_id->us : 0);
@@ -1270,20 +1308,6 @@ void BKE_libblock_remap_locked(Main *bmain, void *old_idv, void *new_idv, const
 		Object *old_ob = (Object *)old_id;
 		Object *new_ob = (Object *)new_id;
 
-		if (new_ob == NULL) {
-			Scene *sce;
-			Base *base;
-
-			for (sce = bmain->scene.first; sce; sce = sce->id.next) {
-				base = BKE_scene_base_find(sce, old_ob);
-
-				if (base) {
-					BKE_scene_base_unlink(sce, base);
-					MEM_freeN(base);
-				}
-			}
-		}
-
 		if (old_ob->flag & OB_FROMGROUP) {
 			/* Note that for Scene's BaseObject->flag, either we:
 			 *     - unlinked old_ob (i.e. new_ob is NULL), in which case scenes' bases have been removed already.
@@ -1313,21 +1337,22 @@ void BKE_libblock_remap_locked(Main *bmain, void *old_idv, void *new_idv, const
 	DAG_relations_tag_update(bmain);
 }
 
-void BKE_libblock_remap(Main *bmain, void *old_idv, void *new_idv, const bool skip_indirect_usage)
+void BKE_libblock_remap(
+        Main *bmain, void *old_idv, void *new_idv, const bool skip_indirect_usage, const bool do_flag_never_null)
 {
 	BKE_main_lock(bmain);
 
-	BKE_libblock_remap_locked(bmain, old_idv, new_idv, skip_indirect_usage);
+	BKE_libblock_remap_locked(bmain, old_idv, new_idv, skip_indirect_usage, do_flag_never_null);
 
 	BKE_main_unlock(bmain);
 }
 
 /** Unlink given \a id from given \a bmain (does not touch to indirect, i.e. library, usages of the ID). */
-void BKE_libblock_unlink(Main *bmain, void *idv)
+void BKE_libblock_unlink(Main *bmain, void *idv, const bool do_flag_never_null)
 {
 	BKE_main_lock(bmain);
 
-	BKE_libblock_remap_locked(bmain, idv, NULL, true);
+	BKE_libblock_remap_locked(bmain, idv, NULL, true, do_flag_never_null);
 
 	BKE_main_unlock(bmain);
 }
@@ -1335,7 +1360,7 @@ 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
+ * \param us_min_never_null If \a 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.) ? */
@@ -1346,7 +1371,8 @@ 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, const bool us_min_never_null)
+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;
@@ -1401,36 +1427,12 @@ void BKE_libblock_free_data(Main *bmain, ID *id)
 	BKE_animdata_main_cb(bmain, animdata_dtar_clear_cb, (void *)id);
 }
 
-typedef struct IDRecursiveDelete {
-	ID *id_used;
-	ID *id_user;
-	bool changed;
-} IDRecursiveDelete;
-
-static bool foreach_libblock_recursive_delete_callback(void *user_data, ID **id_p, int cb_flag)
-{
-	IDRecursiveDelete *id_recursive_delete = user_data;
-	ID *id_used = id_recursive_delete->id_used;
-	ID *id_user = id_recursive_delete->id_user;
-
-	if ((*id_p == id_used) && (cb_flag & IDWALK_NEVER_NULL)) {
-		id_user->flag |= LIB_DOIT;
-		id_recursive_delete->changed = true;
-		return false;  /* No need 

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list