Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBastien Montagne <montagne29@wanadoo.fr>2019-03-18 13:32:06 +0300
committerBastien Montagne <montagne29@wanadoo.fr>2019-03-18 13:36:50 +0300
commitd0e28721b04a0235d4f6bfbe42f43672ff923444 (patch)
treeaf52e9e2f14a7e29eb40731b88584d00e309f821
parent66932a2c814037f897af56693efb68b6993406fb (diff)
Cleanup: Main id looping: add FOREACH_MAIN_LISTBASE macro.
We don't want to use flow control like `break` statement into the basic `FOREACH_MAIN_ID` macro, as this is a nested loop. When refined behavior is needed (like breaking whole iteration, or just skipping to next ID type), FOREACH_MAIN_LISTBASE and FOREACH_MAIN_LISTBASE_ID macros should be used instead. Based on D4382 by @campbellbarton (Other potential solution, using flow control macros: D4384).
-rw-r--r--source/blender/blenkernel/BKE_main.h28
-rw-r--r--source/blender/blenkernel/intern/blendfile.c15
-rw-r--r--source/blender/blenkernel/intern/library_query.c9
-rw-r--r--source/blender/python/intern/bpy_rna_id_collection.c87
4 files changed, 72 insertions, 67 deletions
diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
index 03f9f9a21ea..6b9c35d90d3 100644
--- a/source/blender/blenkernel/BKE_main.h
+++ b/source/blender/blenkernel/BKE_main.h
@@ -152,31 +152,29 @@ struct GSet *BKE_main_gset_create(struct Main *bmain, struct GSet *gset);
} \
} ((void)0)
-
-#define FOREACH_MAIN_ID_BEGIN(_bmain, _id) \
+#define FOREACH_MAIN_LISTBASE_BEGIN(_bmain, _lb) \
{ \
ListBase *_lbarray[MAX_LIBARRAY]; \
int _i = set_listbasepointers(_bmain, _lbarray); \
while (_i--) { \
- FOREACH_MAIN_LISTBASE_ID_BEGIN(_lbarray[_i], _id)
+ _lb = _lbarray[_i];
-#define FOREACH_MAIN_ID_END \
- FOREACH_MAIN_LISTBASE_ID_END; \
+#define FOREACH_MAIN_LISTBASE_END \
} \
} ((void)0)
-/** \param _do_break A boolean, to allow breaking iteration (only used to break by type,
- * you must also use an explicit `break;` operation if you want to
- * immediately break from inner by-ID loop).
- */
-#define FOREACH_MAIN_ID_BREAKABLE_BEGIN(_bmain, _id, _do_break) \
+/* DO NOT use break statement with that macro, use FOREACH_MAIN_LISTBASE and FOREACH_MAIN_LISTBASE_ID instead
+ * if you need that kind of control flow. */
+#define FOREACH_MAIN_ID_BEGIN(_bmain, _id) \
{ \
- ListBase *_lbarray[MAX_LIBARRAY]; \
- int i = set_listbasepointers(_bmain, _lbarray); \
- while (i-- && !_do_break) { \
- FOREACH_MAIN_LISTBASE_ID_BEGIN(_lbarray[i], _id) \
+ ListBase *_lb; \
+ FOREACH_MAIN_LISTBASE_BEGIN(_bmain, _lb) { \
+ FOREACH_MAIN_LISTBASE_ID_BEGIN(_lbarray[_i], _id)
-#define FOREACH_MAIN_ID_BREAKABLE_END FOREACH_MAIN_ID_END
+#define FOREACH_MAIN_ID_END \
+ FOREACH_MAIN_LISTBASE_ID_END; \
+ } FOREACH_MAIN_LISTBASE_END; \
+ } ((void)0)
struct BlendThumbnail *BKE_main_thumbnail_from_imbuf(struct Main *bmain, struct ImBuf *img);
diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c
index 455f73c65c0..cd17911d65d 100644
--- a/source/blender/blenkernel/intern/blendfile.c
+++ b/source/blender/blenkernel/intern/blendfile.c
@@ -460,16 +460,21 @@ bool BKE_blendfile_read_from_memfile(
void BKE_blendfile_read_make_empty(bContext *C)
{
Main *bmain = CTX_data_main(C);
+ ListBase *lb;
ID *id;
- FOREACH_MAIN_ID_BEGIN(bmain, id)
+ FOREACH_MAIN_LISTBASE_BEGIN(bmain, lb)
{
- if (ELEM(GS(id->name), ID_SCE, ID_SCR, ID_WM, ID_WS)) {
- break; /* Only breaks iter on that ID type, and continues with IDs of next type. */
+ FOREACH_MAIN_LISTBASE_ID_BEGIN(lb, id)
+ {
+ if (ELEM(GS(id->name), ID_SCE, ID_SCR, ID_WM, ID_WS)) {
+ break;
+ }
+ BKE_id_delete(bmain, id);
}
- BKE_id_delete(bmain, id);
+ FOREACH_MAIN_LISTBASE_ID_END;
}
- FOREACH_MAIN_ID_END;
+ FOREACH_MAIN_LISTBASE_END;
}
/* only read the userdef from a .blend */
diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c
index 72e9d747206..9861b232dd9 100644
--- a/source/blender/blenkernel/intern/library_query.c
+++ b/source/blender/blenkernel/intern/library_query.c
@@ -1384,19 +1384,16 @@ void BKE_library_unused_linked_data_set_tag(Main *bmain, const bool do_init_tag)
}
for (bool do_loop = true; do_loop; ) {
- bool do_break = false;
do_loop = false;
- FOREACH_MAIN_ID_BREAKABLE_BEGIN(bmain, id, do_break)
+ FOREACH_MAIN_ID_BEGIN(bmain, id)
{
+ /* We only want to check that ID if it is currently known as used... */
if ((id->tag & LIB_TAG_DOIT) == 0) {
BKE_library_foreach_ID_link(
bmain, id, foreach_libblock_used_linked_data_tag_clear_cb, &do_loop, IDWALK_READONLY);
}
- /* Else it is an unused ID (so far), no need to check it further. */
- do_break = true;
- break;
}
- FOREACH_MAIN_ID_BREAKABLE_END;
+ FOREACH_MAIN_ID_END;
}
}
diff --git a/source/blender/python/intern/bpy_rna_id_collection.c b/source/blender/python/intern/bpy_rna_id_collection.c
index 31b135fe933..7a5849f818d 100644
--- a/source/blender/python/intern/bpy_rna_id_collection.c
+++ b/source/blender/python/intern/bpy_rna_id_collection.c
@@ -159,6 +159,7 @@ static PyObject *bpy_user_map(PyObject *UNUSED(self), PyObject *args, PyObject *
#else
Main *bmain = G_MAIN; /* XXX Ugly, but should work! */
#endif
+ ListBase *lb;
ID *id;
PyObject *subset = NULL;
@@ -223,57 +224,61 @@ static PyObject *bpy_user_map(PyObject *UNUSED(self), PyObject *args, PyObject *
data_cb.types_bitmap = key_types_bitmap;
- FOREACH_MAIN_ID_BEGIN(bmain, id)
+ FOREACH_MAIN_LISTBASE_BEGIN(bmain, lb)
{
- /* We cannot skip here in case we have some filter on key types... */
- if (key_types_bitmap == NULL && val_types_bitmap != NULL) {
- if (!id_check_type(id, val_types_bitmap)) {
- break; /* Break iter on that type of IDs, continues with next ID type. */
+ FOREACH_MAIN_LISTBASE_ID_BEGIN(lb, id)
+ {
+ /* We cannot skip here in case we have some filter on key types... */
+ if (key_types_bitmap == NULL && val_types_bitmap != NULL) {
+ if (!id_check_type(id, val_types_bitmap)) {
+ break;
+ }
}
- }
- /* One-time init, ID is just used as placeholder here, we abuse this in iterator callback
- * to avoid having to rebuild a complete bpyrna object each time for the key searching
- * (where only ID pointer value is used). */
- if (data_cb.py_id_key_lookup_only == NULL) {
- data_cb.py_id_key_lookup_only = pyrna_id_CreatePyObject(id);
- }
+ /* One-time init, ID is just used as placeholder here, we abuse this in iterator callback
+ * to avoid having to rebuild a complete bpyrna object each time for the key searching
+ * (where only ID pointer value is used). */
+ if (data_cb.py_id_key_lookup_only == NULL) {
+ data_cb.py_id_key_lookup_only = pyrna_id_CreatePyObject(id);
+ }
- if (!data_cb.is_subset &&
- /* We do not want to pre-add keys of flitered out types. */
- (key_types_bitmap == NULL || id_check_type(id, key_types_bitmap)) &&
- /* We do not want to pre-add keys when we have filter on value types, but not on key types. */
- (val_types_bitmap == NULL || key_types_bitmap != NULL))
- {
- PyObject *key = data_cb.py_id_key_lookup_only;
- PyObject *set;
-
- RNA_id_pointer_create(id, &((BPy_StructRNA *)key)->ptr);
-
- /* We have to insert the key now, otherwise ID unused would be missing from final dict... */
- if ((set = PyDict_GetItem(data_cb.user_map, key)) == NULL) {
- /* Cannot use our placeholder key here! */
- key = pyrna_id_CreatePyObject(id);
- set = PySet_New(NULL);
- PyDict_SetItem(data_cb.user_map, key, set);
- Py_DECREF(set);
- Py_DECREF(key);
+ if (!data_cb.is_subset &&
+ /* We do not want to pre-add keys of flitered out types. */
+ (key_types_bitmap == NULL || id_check_type(id, key_types_bitmap)) &&
+ /* We do not want to pre-add keys when we have filter on value types, but not on key types. */
+ (val_types_bitmap == NULL || key_types_bitmap != NULL))
+ {
+ PyObject *key = data_cb.py_id_key_lookup_only;
+ PyObject *set;
+
+ RNA_id_pointer_create(id, &((BPy_StructRNA *)key)->ptr);
+
+ /* We have to insert the key now, otherwise ID unused would be missing from final dict... */
+ if ((set = PyDict_GetItem(data_cb.user_map, key)) == NULL) {
+ /* Cannot use our placeholder key here! */
+ key = pyrna_id_CreatePyObject(id);
+ set = PySet_New(NULL);
+ PyDict_SetItem(data_cb.user_map, key, set);
+ Py_DECREF(set);
+ Py_DECREF(key);
+ }
}
- }
- if (val_types_bitmap != NULL && !id_check_type(id, val_types_bitmap)) {
- continue;
- }
+ if (val_types_bitmap != NULL && !id_check_type(id, val_types_bitmap)) {
+ continue;
+ }
- data_cb.id_curr = id;
- BKE_library_foreach_ID_link(NULL, id, foreach_libblock_id_user_map_callback, &data_cb, IDWALK_CB_NOP);
+ data_cb.id_curr = id;
+ BKE_library_foreach_ID_link(NULL, id, foreach_libblock_id_user_map_callback, &data_cb, IDWALK_CB_NOP);
- if (data_cb.py_id_curr) {
- Py_DECREF(data_cb.py_id_curr);
- data_cb.py_id_curr = NULL;
+ if (data_cb.py_id_curr) {
+ Py_DECREF(data_cb.py_id_curr);
+ data_cb.py_id_curr = NULL;
+ }
}
+ FOREACH_MAIN_LISTBASE_ID_END;
}
- FOREACH_MAIN_ID_END;
+ FOREACH_MAIN_LISTBASE_ID_END;
ret = data_cb.user_map;