[Bf-blender-cvs] [f0c6c85] id-remap: Attempt to fix the 'user_one' mess...

Bastien Montagne noreply at git.blender.org
Fri Nov 6 18:01:02 CET 2015


Commit: f0c6c85788ac7ba9f8edef0b7d331c72965ab004
Author: Bastien Montagne
Date:   Fri Nov 6 18:00:09 2015 +0100
Branches: id-remap
https://developer.blender.org/rBf0c6c85788ac7ba9f8edef0b7d331c72965ab004

Attempt to fix the 'user_one' mess...

Seems to work (though will need much more tests), but makes code more ugly. :|

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

M	source/blender/blenkernel/BKE_library.h
M	source/blender/blenkernel/BKE_screen.h
M	source/blender/blenkernel/intern/library.c
M	source/blender/blenkernel/intern/screen.c
M	source/blender/editors/include/ED_util.h
M	source/blender/editors/space_buttons/space_buttons.c
M	source/blender/editors/space_clip/space_clip.c
M	source/blender/editors/space_image/space_image.c
M	source/blender/editors/space_logic/space_logic.c
M	source/blender/editors/space_node/space_node.c
M	source/blender/editors/space_outliner/space_outliner.c
M	source/blender/editors/space_sequencer/space_sequencer.c
M	source/blender/editors/space_text/space_text.c
M	source/blender/editors/space_view3d/space_view3d.c
M	source/blender/editors/util/ed_util.c
M	source/blender/windowmanager/WM_api.h
M	source/blender/windowmanager/intern/wm_event_system.c

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

diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index 090145d..770010d 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -127,7 +127,7 @@ struct ID *BKE_libblock_find_name(const short type, const char *name) ATTR_WARN_
 
 void BKE_library_callback_free_window_manager_set(void (*func)(struct bContext *, struct wmWindowManager *));
 void BKE_library_callback_free_notifier_reference_set(void (*func)(const void *));
-void BKE_library_callback_remap_editor_id_reference_set(void (*func)(struct ID *, struct ID *));
+void BKE_library_callback_remap_editor_id_reference_set(bool (*func)(struct ID *, struct ID *));
 
 /* use when "" is given to new_id() */
 #define ID_FALLBACK_NAME N_("Untitled")
diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h
index d74a61c..e89888c 100644
--- a/source/blender/blenkernel/BKE_screen.h
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -99,7 +99,7 @@ typedef struct SpaceType {
 	int (*context)(const struct bContext *, const char *, struct bContextDataResult *);
 
 	/* Used when we want to replace an ID by another (or NULL). */
-	void (*id_remap)(struct ScrArea *, struct SpaceLink *, struct ID *, struct ID *);
+	bool (*id_remap)(struct ScrArea *, struct SpaceLink *, struct ID *, struct ID *);
 
 	/* region type definitions */
 	ListBase regiontypes;
@@ -276,7 +276,7 @@ void BKE_spacedata_freelist(ListBase *lb);
 void BKE_spacedata_copylist(ListBase *lb1, ListBase *lb2);
 void BKE_spacedata_draw_locks(int set);
 
-void BKE_spacedata_callback_id_remap_set(void (*func)(struct ScrArea *, struct SpaceLink *, struct ID *, struct ID *));
+void BKE_spacedata_callback_id_remap_set(bool (*func)(struct ScrArea *, struct SpaceLink *, struct ID *, struct ID *));
 void BKE_spacedata_id_unref(struct ScrArea *sa, struct SpaceLink *sl, struct ID *id);
 
 /* area/regions */
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 4de1909..e4b2459 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -982,9 +982,9 @@ void BKE_library_callback_free_notifier_reference_set(void (*func)(const void *)
 	free_notifier_reference_cb = func;
 }
 
-static void (*remap_editor_id_reference_cb)(ID *, ID *) = NULL;
+static bool (*remap_editor_id_reference_cb)(ID *, ID *) = NULL;
 
-void BKE_library_callback_remap_editor_id_reference_set(void (*func)(ID *, ID *))
+void BKE_library_callback_remap_editor_id_reference_set(bool (*func)(ID *, ID *))
 {
 	remap_editor_id_reference_cb = func;
 }
@@ -994,10 +994,11 @@ typedef struct IDRemap {
 	ID *old_id;
 	ID *new_id;
 	ID *id;  /* The ID in which we are replacing old_id by new_id usages. */
-	/* XXX TODO: keeping this for now (also as debug data), in theory we can get rid of it. */
-	int skipped_direct;  /* Number of direct usecase that could not be remapped (e.g.: obdata when in edit mode). */
-	int skipped_indirect;  /* Number of indirect usecase that could not be remapped. */
 	int flag;
+
+	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;
 
 enum {
@@ -1006,6 +1007,8 @@ enum {
 
 	/* Set by callback. */
 	ID_REMAP_IS_LINKED_DIRECT     = 1 << 16,  /* new_id is directly linked in current .blend. */
+	ID_REMAP_IS_USER_ONE          = 1 << 17,  /* old_id was used by some nasty 'user_one' stuff (like image editor). */
+	ID_REMAP_IS_USER_ONE_SKIPPED  = 1 << 18,  /* 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)
@@ -1030,18 +1033,29 @@ static bool foreach_libblock_remap_callback(void *user_data, ID **id_p, int cb_f
 		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));
 
 		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_obj_editmode && (((Object *)id)->data == *id_p)) || (skip_indirect && (is_proxy || is_indirect))) {
-			if (is_proxy || is_obj_editmode) {
+		if (is_never_null ||
+		    (is_obj_editmode && (((Object *)id)->data == *id_p)) ||
+		    (skip_indirect && (is_proxy || is_indirect)))
+		{
+			if (is_never_null || is_proxy || is_obj_editmode) {
 				id_remap_data->skipped_direct++;
 			}
 			else {
 				id_remap_data->skipped_indirect++;
 			}
+			if (cb_flag & IDWALK_USER) {
+				id_remap_data->skipped_refcounted++;
+			}
+			else if (cb_flag & IDWALK_USER_ONE) {
+				/* We cannot affect old_id->us directly, flag it as such for final handling... */
+				id_remap_data->flag |= ID_REMAP_IS_USER_ONE_SKIPPED;
+			}
 		}
 		else {
 			*id_p = new_id;
@@ -1050,6 +1064,11 @@ static bool foreach_libblock_remap_callback(void *user_data, ID **id_p, int cb_f
 				if (new_id)
 					new_id->us++;
 			}
+			else if (cb_flag & IDWALK_USER_ONE) {
+				id_us_ensure_real(new_id);
+				/* We cannot affect old_id->us directly, flag it as such for final handling... */
+				id_remap_data->flag |= ID_REMAP_IS_USER_ONE;
+			}
 			DAG_id_tag_update_ex(bmain, id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
 			if (!is_indirect) {
 				id_remap_data->flag |= ID_REMAP_IS_LINKED_DIRECT;
@@ -1060,25 +1079,54 @@ static bool foreach_libblock_remap_callback(void *user_data, ID **id_p, int cb_f
 	return true;
 }
 
-static void libblock_remap_do(
-        Main *bmain, ID *id, ID *old_id, ID *new_id, const bool skip_indirect_usage,
-        int *r_skipped_direct, int *r_skipped_indirect)
+/**
+ * Execute the 'data' part of the remapping (that is, all ID pointers from other ID datablocks).
+ *
+ * Behavior differs depending on whether given \a id is NULL or not:
+ *   - \a id NULL: \a old_id must be non-NULL, \a new_id may be NULL (unlinking \a old_id) or not
+ *     (remapping \a old_id to \a new_id). The whole \a bmain database is checked, and all pointers to \a old_id
+ *     are remapped to \a new_id.
+ *   - \a id is non-NULL:
+ *     + If \a old_id is NULL, \a new_id must also be NULL, and all ID pointers from \a id are cleared (i.e. \a id
+ *       does not references any other datablock anymore).
+ *     + If \a old_id is non-NULL, behavior is as with a NULL \a id, but only for given \a id.
+ *
+ * \param bmain the Main data storage to operate on (if \a id is NULL).
+ * \param id the datablock to operate on (may be NULL).
+ * \param old_id the datablock to dereference (may be NULL if \a id is non-NULL).
+ * \param new_id the new datablock to replace \a old_id references with (may be NULL).
+ * \param skip_indirect_usage if true, do not remap/unlink indirect usages of \a old_id datablock.
+ * \param r_skipped_direct if non-NULL, the number of direct references that could not be replaced.
+ * \param r_skipped_indirect if non-NULL, the number of indirect references that could not be replaced.
+ * \param r_skipped_refcounted if non-NULL, the number of refcounted references that could not be replaced.
+ * \return true is there was some 'user_one' users of \a old_id (needed to handle correctly #old_id->us count).
+ */
+static bool libblock_remap_data(
+        Main *bmain, ID *id, ID *old_id, ID *new_id, const bool skip_indirect_usage, IDRemap *r_id_remap_data)
 {
-	IDRemap id_remap_data = {bmain, old_id, new_id, NULL};
+	IDRemap id_remap_data;
 	ListBase *lb_array[MAX_LIBARRAY];
 	int i;
 
+	if (r_id_remap_data == NULL) {
+		r_id_remap_data = &id_remap_data;
+	}
+	r_id_remap_data->bmain = bmain;
+	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->skipped_direct = 0;
+	r_id_remap_data->skipped_indirect = 0;
+	r_id_remap_data->skipped_refcounted = 0;
+
 	printf("%s: %s (%p) replaced by %s (%p)\n", __func__,
 	       old_id ? old_id->name : "", old_id, new_id ? new_id->name : "", new_id);
 
-	if (skip_indirect_usage) {
-		id_remap_data.flag |= ID_REMAP_SKIP_INDIRECT_USAGE;
-	}
-
 	if (id) {
 		printf("\tchecking id %s (%p, %p)\n", id->name, id, id->lib);
-		id_remap_data.id = id;
-		BKE_library_foreach_ID_link(id, foreach_libblock_remap_callback, (void *)&id_remap_data, IDWALK_NOP);
+		r_id_remap_data->id = id;
+		BKE_library_foreach_ID_link(id, foreach_libblock_remap_callback, (void *)r_id_remap_data, IDWALK_NOP);
 	}
 	else {
 		i = set_listbasepointers(bmain, lb_array);
@@ -1094,38 +1142,37 @@ static void libblock_remap_do(
 				 * the user count handling...
 				 * XXX No more true (except for debug usage of those skipping counters). */
 				printf("\tchecking id %s (%p, %p)\n", id->name, id, id->lib);
-				id_remap_data.id = id;
-				BKE_library_foreach_ID_link(id, foreach_libblock_remap_callback, (void *)&id_remap_data, IDWALK_NOP);
+				r_id_remap_data->id = id;
+				BKE_library_foreach_ID_link(id, foreach_libblock_remap_callback, (void *)r_id_remap_data, IDWALK_NOP);
 			}
 		}
 	}
 
 	if (old_id && (old_id->flag & LIB_FAKEUSER)) {
-		id_remap_data.skipped_direct++;
+		r_id_remap_data->skipped_direct++;
+		r_id_remap_data->skipped_refcounted++;
 	}
 
-	if (new_id && (new_id->flag & LIB_INDIRECT) && (id_remap_data.flag & ID_REMAP_IS_LINKED_DIRECT)) {
+	if (new_id && (new_id->flag & LIB_INDIRECT) && (r_id_remap_data->flag & ID_REMAP_IS_LINKED_DIRECT)) {
 		new_id->flag &= ~LIB_INDIRECT;
 		new_id->flag |= LIB_EXTERN;
 	}
 
-	if (r_skipped_direct)
-		*r_skipped_direct = id_remap_data.skipped_direct;
-
-	if (r_skipped_indirect)
-		*r_skipped_indirect = id_remap_data.skipped_indirect;
-
 	printf("%s: %d occurences skipped (%d direct and %d indirect ones)\n", __

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list