[Bf-blender-cvs] [f59b6ff] render-layers: Using an iterator to go over objects, and use this for library_query

Dalai Felinto noreply at git.blender.org
Mon Dec 19 17:58:07 CET 2016


Commit: f59b6ff4108f66e066ba85d15bc2c8c59913b643
Author: Dalai Felinto
Date:   Mon Dec 19 14:07:21 2016 +0100
Branches: render-layers
https://developer.blender.org/rBf59b6ff4108f66e066ba85d15bc2c8c59913b643

Using an iterator to go over objects, and use this for library_query

This is not the ideal iterator (it loops over the scene collection tree 3x).
One solution (I want to discuss with Bastien Montagne @mont29) is whether to store the *parent of a SceneCollection to help with that. That would speed things up, and cost less memory.

We do not even need to store it in the file, since it can be re-generated at read time

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

M	source/blender/blenkernel/BKE_collection.h
M	source/blender/blenkernel/intern/collection.c
M	source/blender/blenkernel/intern/library_query.c
M	source/blender/blenlib/BLI_ghash.h
M	source/blender/editors/object/object_relations.c

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

diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h
index 61d53da..3185f82 100644
--- a/source/blender/blenkernel/BKE_collection.h
+++ b/source/blender/blenkernel/BKE_collection.h
@@ -27,7 +27,9 @@
  *  \ingroup bke
  */
 
+#include "BLI_ghash.h"
 #include "BLI_iterator.h"
+#include "DNA_listBase.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -46,17 +48,43 @@ void BKE_collection_object_add(struct Scene *scene, struct SceneCollection *sc,
 void BKE_collection_object_remove(struct Scene *scene, struct SceneCollection *sc, struct Object *object);
 
 typedef void (*BKE_scene_objects_Cb)(struct Object *ob, void *data);
+typedef void (*BKE_scene_collections_Cb)(struct SceneCollection *ob, void *data);
+
+void BKE_scene_collections_callback(struct Scene *scene, BKE_scene_collections_Cb callback, void *data);
 void BKE_scene_objects_callback(struct Scene *scene, BKE_scene_objects_Cb callback, void *data);
 
 /* iterators */
 void BKE_scene_objects_Iterator_begin(struct Iterator *iter, void *data);
+void BKE_scene_collections_Iterator_begin(struct Iterator *iter, void *data);
+
+typedef struct SceneCollectionIterData {
+	struct SceneCollection *sc;
+	struct SceneCollectionIterData *parent;
+} SceneCollectionIterData;
 
-#define SCENE_OBJECTS_BEGIN(scene, _ob)                                       \
-	ITER_BEGIN(BKE_scene_objects_Iterator_begin, scene, _ob)
+#define FOREACH_SCENE_COLLECTION(scene, _sc)                                  \
+	ITER_BEGIN(BKE_scene_collections_Iterator_begin, scene, _sc)
 
-#define SCENE_OBJECTS_END                                                     \
+#define FOREACH_SCENE_COLLECTION_END                                          \
 	ITER_END
 
+#define FOREACH_SCENE_OBJECT(scene, _ob)                                      \
+{                                                                             \
+	GSet *visited = BLI_gset_ptr_new(__func__);                               \
+	SceneCollection *sc;                                                      \
+	FOREACH_SCENE_COLLECTION(scene, sc)                                       \
+	for (LinkData *link = sc->objects.first; link; link = link->next) {       \
+	    _ob = link->data;                                                     \
+	    if (!BLI_gset_haskey(visited, ob)) {                                  \
+	        BLI_gset_add(visited, ob);
+
+#define FOREACH_SCENE_OBJECT_END                                              \
+        }                                                                     \
+    }                                                                         \
+	FOREACH_SCENE_COLLECTION_END                                              \
+	BLI_gset_free(visited, NULL);                                             \
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index 8a7393b..81d8d26 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -25,6 +25,7 @@
  */
 
 #include "BLI_blenlib.h"
+#include "BLI_ghash.h"
 #include "BLI_iterator.h"
 #include "BLI_listbase.h"
 #include "BLT_translation.h"
@@ -199,102 +200,56 @@ void BKE_collection_object_remove(struct Scene *UNUSED(scene), struct SceneColle
 	 * also remove all reference to ob in the filter_objects */
 }
 
-/*
- * Tag util functions to make sure the same object is not called twice
- */
-
-static void object_tag(Object *ob)
-{
-	ob->flag |= BA_TEMP_TAG;
-}
-
-static void object_tag_clear(Object *ob, void *UNUSED(data))
-{
-	ob->flag &= ~BA_TEMP_TAG;
-}
-
-static bool object_tag_test(Object *ob)
-{
-	return (ob->flag & BA_TEMP_TAG) != 0;
-}
+/* ---------------------------------------------------------------------- */
+/* Iteractors */
 
-/*
- * Recursively calls the callback function for the objects in a SceneCollection
- */
-static void collection_objects_callback(SceneCollection *sc, BKE_scene_objects_Cb callback, void *data)
+static void scene_collection_callback(SceneCollection *sc, BKE_scene_collections_Cb callback, void *data)
 {
-	for (LinkData *link= sc->objects.first; link; link = link->next) {
-		if (object_tag_test(link->data)) {
-			callback(link->data, data);
-			object_tag(link->data);
-		}
-	}
-
-	for (LinkData *link= sc->filter_objects.first; link; link = link->next) {
-		callback(link->data, data);
-	}
+	callback(sc, data);
 
 	for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
-		collection_objects_callback(nsc, callback, data);
+		scene_collection_callback(nsc, callback, data);
 	}
 }
 
-/*
- * Recursively calls the callback function for the objects in a Scene
- * The same object
- */
-void BKE_scene_objects_callback(Scene *scene, BKE_scene_objects_Cb callback, void *data)
-{
-	SceneCollection *sc = BKE_collection_master(scene);
-	collection_objects_callback(sc, object_tag_clear, NULL);
-	collection_objects_callback(sc, callback, data);
-}
-
-
-/* ---------------------------------------------------------------------- */
-/* Iteractors */
-
-/* sequence strip iterator:
- * - builds a full array, recursively into meta strips
- */
-
-static void scene_objects_count(Object *UNUSED(ob), void *data)
+static void scene_collections_count(SceneCollection *UNUSED(sc), void *data)
 {
 	int *tot = data;
 	(*tot)++;
 }
 
-static void scene_objects_build_array(Object *ob, void *data)
+static void scene_collections_build_array(SceneCollection *sc, void *data)
 {
-	Object ***array = data;
-	**array = ob;
+	SceneCollection ***array = data;
+	**array = sc;
 	(*array)++;
 }
 
-static void scene_objects_array(Scene *scene, Object ***objects_array, int *tot)
+static void scene_collections_array(Scene *scene, SceneCollection ***collections_array, int *tot)
 {
-	Object **array;
+	SceneCollection *sc = BKE_collection_master(scene);
+	SceneCollection **array;
 
-	*objects_array = NULL;
+	*collections_array = NULL;
 	*tot = 0;
 
 	if (scene == NULL)
 		return;
 
-	BKE_scene_objects_callback(scene, scene_objects_count, tot);
+	scene_collection_callback(sc, scene_collections_count, tot);
 
 	if (*tot == 0)
 		return;
 
-	*objects_array = array = MEM_mallocN(sizeof(Object *) * (*tot), "ObjectsArray");
-	BKE_scene_objects_callback(scene, scene_objects_build_array, &array);
+	*collections_array = array = MEM_mallocN(sizeof(SceneCollection *) * (*tot), "SceneCollectionArray");
+	scene_collection_callback(sc, scene_collections_build_array, &array);
 }
 
 /*
  * Only use this in non-performance critical situations
  * (it iterates over all scene collections twice)
  */
-void BKE_scene_objects_Iterator_begin(Iterator *iter, void *data)
+void BKE_scene_collections_Iterator_begin(Iterator *iter, void *data)
 {
-	scene_objects_array(data, (Object ***)&iter->array, &iter->tot);
+	scene_collections_array(data, (SceneCollection ***)&iter->array, &iter->tot);
 }
diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c
index 1601348..9869f10 100644
--- a/source/blender/blenkernel/intern/library_query.c
+++ b/source/blender/blenkernel/intern/library_query.c
@@ -388,11 +388,11 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
 
 				{
 					Object* ob;
-					SCENE_OBJECTS_BEGIN(scene, ob)
+					FOREACH_SCENE_OBJECT(scene, ob)
 					{
 						CALLBACK_INVOKE(ob, IDWALK_USER);
 					}
-					SCENE_OBJECTS_END
+					FOREACH_SCENE_OBJECT_END
 				}
 
 				for (TimeMarker *marker = scene->markers.first; marker; marker = marker->next) {
diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h
index 7e3a009..068c188 100644
--- a/source/blender/blenlib/BLI_ghash.h
+++ b/source/blender/blenlib/BLI_ghash.h
@@ -32,6 +32,7 @@
  *  \ingroup bli
  */
 
+#include "BLI_blenlib.h"
 #include "BLI_sys_types.h" /* for bool */
 #include "BLI_compiler_attrs.h"
 
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 6722c8d..553a844 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -1854,11 +1854,11 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
 void ED_object_single_user(Main *bmain, Scene *scene, Object *ob)
 {
 	Object *ob_iter;
-	SCENE_OBJECTS_BEGIN(scene, ob_iter)
+	FOREACH_SCENE_OBJECT(scene, ob_iter)
 	{
 		ob_iter->flag &= ~OB_DONE;
 	}
-	SCENE_OBJECTS_END
+	FOREACH_SCENE_OBJECT_END
 
 	/* tag only the one object */
 	ob->flag |= OB_DONE;




More information about the Bf-blender-cvs mailing list