[Bf-blender-cvs] [bfad4bb] id-remap: Add helpers to BKE_library_query to find which datablocks are using/referencing a given ID.

Bastien Montagne noreply at git.blender.org
Thu Nov 26 12:43:13 CET 2015


Commit: bfad4bba7a4e4601c0aa9b14c553fa31e287da74
Author: Bastien Montagne
Date:   Wed Nov 25 20:48:22 2015 +0100
Branches: id-remap
https://developer.blender.org/rBbfad4bba7a4e4601c0aa9b14c553fa31e287da74

Add helpers to BKE_library_query to find which datablocks are using/referencing a given ID.

Also expose this in RNA. Priceless to debug ID usages...

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

M	source/blender/blenkernel/BKE_library_query.h
M	source/blender/blenkernel/intern/library_query.c
M	source/blender/makesrna/intern/makesrna.c
M	source/blender/makesrna/intern/rna_ID.c

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

diff --git a/source/blender/blenkernel/BKE_library_query.h b/source/blender/blenkernel/BKE_library_query.h
index 194b6f0..4e2142f 100644
--- a/source/blender/blenkernel/BKE_library_query.h
+++ b/source/blender/blenkernel/BKE_library_query.h
@@ -32,6 +32,7 @@
  */
 
 struct ID;
+struct Main;
 
 /* Tips for the callback for cases it's gonna to modify the pointer. */
 enum {
@@ -65,4 +66,13 @@ enum {
 void BKE_library_foreach_ID_link(struct ID *id, LibraryIDLinkCallback callback, void *user_data, int flag);
 void BKE_library_update_ID_link_user(struct ID *id_dst, struct ID *id_src, const int cd_flag);
 
+/* Iterator over all ID users of a given datablock. */
+struct IDUsersIter;
+
+int BKE_library_ID_use_ID(struct ID *id_user, struct ID *id_used);
+
+struct IDUsersIter *BKE_library_ID_users_iter_init(struct Main *bmain, struct ID *id);
+struct ID *BKE_library_ID_users_iter_next(struct IDUsersIter *iter, int *r_count);
+void BKE_library_ID_users_iter_end(struct IDUsersIter **iter);
+
 #endif  /* __BKE_LIBRARY_QUERY_H__ */
diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c
index f809866..ae6d116 100644
--- a/source/blender/blenkernel/intern/library_query.c
+++ b/source/blender/blenkernel/intern/library_query.c
@@ -29,6 +29,7 @@
 
 #include <stdlib.h>
 
+#include "MEM_guardedalloc.h"
 
 #include "DNA_actuator_types.h"
 #include "DNA_anim_types.h"
@@ -61,12 +62,14 @@
 #include "DNA_world_types.h"
 
 #include "BLI_utildefines.h"
+#include "BLI_listbase.h"
 
 #include "BKE_animsys.h"
 #include "BKE_constraint.h"
 #include "BKE_fcurve.h"
 #include "BKE_library.h"
 #include "BKE_library_query.h"
+#include "BKE_main.h"
 #include "BKE_modifier.h"
 #include "BKE_particle.h"
 #include "BKE_rigidbody.h"
@@ -706,3 +709,125 @@ void BKE_library_update_ID_link_user(ID *id_dst, ID *id_src, const int cd_flag)
 		id_us_ensure_real(id_dst);
 	}
 }
+
+/* ***** ID users iterator. ***** */
+typedef struct IDUsersIter {
+	ID *id;
+
+	ListBase *lb_array[MAX_LIBARRAY];
+	int lb_idx;
+
+	ID *curr_id;
+	int count;  /* Set by callback. */
+} IDUsersIter;
+
+static bool foreach_libblock_id_users_callback(void *user_data, ID **id_p, int UNUSED(cb_flag))
+{
+	IDUsersIter *iter = user_data;
+
+	if (*id_p && (*id_p == iter->id)) {
+		iter->count++;
+	}
+
+	return true;
+}
+
+/**
+ * Return the number of times given \a id_user uses/references \a id_used.
+ *
+ * \note This only checks for pointer references of an ID, shallow usages (like e.g. by RNA paths, as done
+ *       for FCurves) are not detected at all.
+ *
+ * \param id_user the ID which is supposed to use (reference) \a id_used.
+ * \param id_used the ID which is supposed to be used (referenced) by \a id_user.
+ * \return the number of direct usages/references of \a id_used by \a id_user.
+ */
+int BKE_library_ID_use_ID(ID *id_user, ID *id_used)
+{
+	IDUsersIter iter;
+
+	/* We do not care about iter.lb_array/lb_idx here... */
+	iter.id = id_used;
+	iter.curr_id = id_user;
+	iter.count = 0;
+
+	BKE_library_foreach_ID_link(iter.curr_id, foreach_libblock_id_users_callback, (void *)&iter, IDWALK_NOP);
+
+	return iter.count;
+}
+
+/**
+ * Initialize an id user iterator.
+ *
+ * \param bmain the Main database in which to search for \a id users.
+ * \param id the datablock to find users of.
+ * \return an opaque pointer to the initialized iterator.
+ */
+IDUsersIter *BKE_library_ID_users_iter_init(Main *bmain, ID *id)
+{
+	IDUsersIter *iter = MEM_mallocN(sizeof(*iter), __func__);
+
+	iter->id = id;
+	iter->lb_idx = set_listbasepointers(bmain, iter->lb_array);
+	iter->curr_id = NULL;
+	iter->count = 0;
+
+	return iter;
+}
+
+/**
+ * @brief BKE_library_ID_users_iter_next
+ *
+ * \param iter the iterator pointer (as returned by \a BKE_library_ID_users_iter_init).
+ * \param r_count if non-null, will be set to the number of usages detected for returned ID.
+ * \return a pointer to the next ID using the searched datablock, or NULL if none found anymore.
+ */
+ID *BKE_library_ID_users_iter_next(IDUsersIter *iter, int *r_count)
+{
+	ID *ret = NULL;
+
+	if (iter == NULL) {
+		if (r_count) {
+			*r_count = 0;
+		}
+		return ret;
+	}
+
+	iter->count = 0;
+	while (ret == NULL) {
+		while (iter->curr_id == NULL) {
+			if (iter->lb_idx-- == 0) {
+				break;
+			}
+			iter->curr_id = iter->lb_array[iter->lb_idx]->first;
+		}
+		if (iter->curr_id == NULL) {
+			break;
+		}
+
+		iter->count = 0;
+		BKE_library_foreach_ID_link(iter->curr_id, foreach_libblock_id_users_callback, (void *)iter, IDWALK_NOP);
+
+		if (iter->count > 0) {
+			ret = iter->curr_id;
+		}
+
+		iter->curr_id = iter->curr_id->next;
+	}
+
+	if (r_count) {
+		*r_count = iter->count;
+	}
+	return ret;
+}
+
+/**
+ * Finalize (clean up) an IDUsers iterator.
+ *
+ * @param iter the address of the iterator pointer to finalize.
+ */
+void BKE_library_ID_users_iter_end(IDUsersIter **iter)
+{
+	MEM_SAFE_FREE(*iter);
+}
+
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index 887124f..1167758 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -3853,6 +3853,8 @@ static void rna_generate_header_cpp(BlenderRNA *UNUSED(brna), FILE *f)
 	fprintf(f, "#include \"RNA_types.h\"\n");
 	fprintf(f, "#include \"RNA_access.h\"\n");
 
+	fprintf(f, "#include \"DNA_listBase.h\"\n");
+
 	fprintf(f, "%s", cpp_classes);
 
 	fprintf(f, "/**************** Declarations ****************/\n\n");
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 579d8ac..a131392 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -87,9 +87,12 @@ EnumPropertyItem rna_enum_id_type_items[] = {
 
 #include "DNA_anim_types.h"
 
+#include "BLI_listbase.h"
+
 #include "BKE_font.h"
 #include "BKE_idprop.h"
 #include "BKE_library.h"
+#include "BKE_library_query.h"
 #include "BKE_animsys.h"
 #include "BKE_material.h"
 #include "BKE_depsgraph.h"
@@ -338,6 +341,27 @@ static void rna_ID_user_remap(ID *id, Main *bmain, ID *new_id)
 	}
 }
 
+static ListBase rna_ID_used_by_ids(ID *id, Main *bmain)
+{
+	ListBase ret = {0};
+	struct IDUsersIter *iter = BKE_library_ID_users_iter_init(bmain, id);
+	ID *id_user;
+
+	do {
+		id_user = BKE_library_ID_users_iter_next(iter, NULL);
+
+		if (id_user) {
+			CollectionPointerLink *lnk = MEM_mallocN(sizeof(*lnk), __func__);
+			RNA_id_pointer_create(id_user, &lnk->ptr);
+			BLI_addtail(&ret, lnk);
+		}
+	} while (id_user != NULL);
+
+	BKE_library_ID_users_iter_end(&iter);
+
+	return ret;
+}
+
 static AnimData * rna_ID_animation_data_create(ID *id, Main *bmain)
 {
 	AnimData *adt = BKE_animdata_add_id(id);
@@ -988,6 +1012,20 @@ static void rna_def_ID(BlenderRNA *brna)
 	parm = RNA_def_pointer(func, "new_id", "ID", "", "New ID to use");
 	RNA_def_property_flag(parm, PROP_NEVER_NULL);
 
+	func = RNA_def_function(srna, "user_of_id", "BKE_library_ID_use_ID");
+	RNA_def_function_ui_description(func, "Count the number of times that ID uses/references given one");
+	parm = RNA_def_pointer(func, "id", "ID", "", "ID to count usages");
+	RNA_def_property_flag(parm, PROP_NEVER_NULL);
+	parm = RNA_def_int(func, "count", 0, 0, INT_MAX,
+	                   "", "Number of usages/references of given id by current datablock", 0, INT_MAX);
+	RNA_def_function_return(func, parm);
+
+	func = RNA_def_function(srna, "used_by_ids", "rna_ID_used_by_ids");
+	RNA_def_function_ui_description(func, "Return a list of all datablocks using/referencing current one");
+	RNA_def_function_flag(func, FUNC_USE_MAIN);
+	parm = RNA_def_collection(func, "ids", "ID", "", "All datablocks using current ID");
+	RNA_def_function_return(func, parm);
+
 	func = RNA_def_function(srna, "animation_data_create", "rna_ID_animation_data_create");
 	RNA_def_function_flag(func, FUNC_USE_MAIN);
 	RNA_def_function_ui_description(func, "Create animation data to this ID, note that not all ID types support this");




More information about the Bf-blender-cvs mailing list