[Bf-blender-cvs] [df50b8c] id-remap: Add main 'ID remap' function.

Bastien Montagne noreply at git.blender.org
Tue Jul 21 22:43:03 CEST 2015


Commit: df50b8cabfe6b12aa2a34be23e596530038e61d4
Author: Bastien Montagne
Date:   Fri Jul 17 22:44:43 2015 +0200
Branches: id-remap
https://developer.blender.org/rBdf50b8cabfe6b12aa2a34be23e596530038e61d4

Add main 'ID remap' function.

Theoretical code, compiles, but needs to be tested!

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

M	source/blender/blenkernel/BKE_library.h
M	source/blender/blenkernel/intern/library.c

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

diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index 761a81e..040a838 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -53,6 +53,9 @@ void *BKE_libblock_copy_nolib(struct ID *id, const bool do_action) ATTR_NONNULL(
 void *BKE_libblock_copy(struct ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
 void  BKE_libblock_copy_data(struct ID *id, const struct ID *id_from, const bool do_action);
 
+/* 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(struct Main *bmain, struct ID *old_id, struct ID *new_id) ATTR_NONNULL();
+
 void BKE_id_lib_local_paths(struct Main *bmain, struct Library *lib, struct ID *id);
 void id_lib_extern(struct ID *id);
 void BKE_library_filepath_set(struct Library *lib, const char *filepath);
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 9a3f43c..345f5df 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -95,6 +95,7 @@
 #include "BKE_lamp.h"
 #include "BKE_lattice.h"
 #include "BKE_library.h"
+#include "BKE_library_query.h"
 #include "BKE_linestyle.h"
 #include "BKE_mesh.h"
 #include "BKE_material.h"
@@ -888,6 +889,78 @@ void BKE_library_callback_remap_editor_id_reference_set(void (*func)(const ID *,
 	remap_editor_id_reference_cb = func;
 }
 
+
+static bool foreach_libblock_remap_callback(void *user_data, ID **id_p, int UNUSED(cb_flag))
+{
+	Main *bmain = ((void **)user_data)[0];
+	ID *old_id = ((void **)user_data)[1];
+	ID *new_id = ((void **)user_data)[2];
+	ID *id = ((void **)user_data)[3];
+
+	if (*id_p == old_id) {
+		*id_p = new_id;
+		DAG_id_tag_update_ex(bmain, id, OB_RECALC_OB);
+	}
+
+	return true;
+}
+
+/** Replace all references in .blend file to \a old_id by \a new_id. */
+void BKE_libblock_remap(Main *bmain, ID *old_id, ID *new_id)
+{
+	void *user_data[4] = {(void *)bmain, (void *)old_id, (void *)new_id, NULL};
+	ListBase lb_array[MAX_LIBARRAY];
+	int i = MAX_LIBARRAY;
+
+	BLI_assert(GS(old_id->name) == GS(new_id->name));
+
+	set_listbasepointers(bmain, (ListBase **)&lb_array);
+
+	BKE_main_lock(bmain);
+
+	/* Note that this is a very 'bruteforce' approach, maybe we could use some depsgraph to only process
+	 * objects actually using given old_id... But for now this will do. */
+
+	while (i--) {
+		ID *id;
+		for (id = lb_array[i].first; id; id = id->next) {
+			user_data[3] = (void *)id;
+			BKE_library_foreach_ID_link(id, foreach_libblock_remap_callback, (void *)user_data, IDWALK_NOP);
+		}
+	}
+
+	if (free_notifier_reference_cb) {
+		free_notifier_reference_cb(old_id);
+	}
+
+	if (remap_editor_id_reference_cb) {
+		remap_editor_id_reference_cb(old_id, new_id);
+	}
+
+	/* All ID 'users' do not actually incref it, so we just assume all uses of this ID have been cleared... */
+	if ((old_id->us > 1) && (old_id->flag & LIB_FAKEUSER)) {
+		new_id->us += old_id->us - 1;
+		if (new_id->flag & LIB_INDIRECT) {
+			new_id->flag &= ~LIB_INDIRECT;
+			new_id->flag |= LIB_EXTERN;
+		}
+		old_id->us = 1;
+	}
+	else if (old_id->us > 0){
+		new_id->us += old_id->us;
+		if (new_id->flag & LIB_INDIRECT) {
+			new_id->flag &= ~LIB_INDIRECT;
+			new_id->flag |= LIB_EXTERN;
+		}
+		old_id->us = 0;
+	}
+
+	/* Full rebuild of DAG! */
+	DAG_relations_tag_update(bmain);
+
+	BKE_main_unlock(bmain);
+}
+
 static void animdata_dtar_clear_cb(ID *UNUSED(id), AnimData *adt, void *userdata)
 {
 	ChannelDriver *driver;




More information about the Bf-blender-cvs mailing list