Cleanup: get rid of last G.main's in bpy area.
[blender.git] / source / blender / python / intern / bpy_rna_id_collection.c
index 104e3e4..4806c22 100644 (file)
 #include "BKE_library_query.h"
 
 #include "DNA_ID.h"
+/* Those folowing are only to support hack of not listing some internal 'backward' pointers in generated user_map... */
+#include "DNA_object_types.h"
+#include "DNA_key_types.h"
 
-#include "bpy_util.h"
+#include "bpy_capi_utils.h"
 #include "bpy_rna_id_collection.h"
 
 #include "../generic/py_capi_utils.h"
@@ -81,7 +84,7 @@ static bool id_check_type(const ID *id, const BLI_bitmap *types_bitmap)
 }
 
 static int foreach_libblock_id_user_map_callback(
-        void *user_data, ID *UNUSED(self_id), ID **id_p, int UNUSED(cb_flag))
+        void *user_data, ID *self_id, ID **id_p, int UNUSED(cb_flag))
 {
        IDUserMapData *data = user_data;
 
@@ -93,6 +96,15 @@ static int foreach_libblock_id_user_map_callback(
                        }
                }
 
+               if ((GS(self_id->name) == ID_OB) && (id_p == (ID **)&((Object *)self_id)->proxy_from)) {
+                       /* We skip proxy_from here, since it some internal pointer which is not irrelevant info for py/API level. */
+                       return IDWALK_RET_NOP;
+               }
+               else if ((GS(self_id->name) == ID_KE) && (id_p == (ID **)&((Key *)self_id)->from)) {
+                       /* We skip from here, since it some internal pointer which is not irrelevant info for py/API level. */
+                       return IDWALK_RET_NOP;
+               }
+
                /* pyrna_struct_hash() uses ptr.data only,
                 * but pyrna_struct_richcmp() uses also ptr.type,
                 * so we need to create a valid PointerRNA here...
@@ -148,10 +160,9 @@ static PyObject *bpy_user_map(PyObject *UNUSED(self), PyObject *args, PyObject *
        BPy_StructRNA *pyrna = (BPy_StructRNA *)self;
        Main *bmain = pyrna->ptr.data;
 #else
-       Main *bmain = G.main;  /* XXX Ugly, but should work! */
+       Main *bmain = G_MAIN;  /* XXX Ugly, but should work! */
 #endif
 
-       static const char *kwlist[] = {"subset", "key_types", "value_types", NULL};
        PyObject *subset = NULL;
 
        PyObject *key_types = NULL;
@@ -161,9 +172,10 @@ static PyObject *bpy_user_map(PyObject *UNUSED(self), PyObject *args, PyObject *
 
        PyObject *ret = NULL;
 
-
-       if (!PyArg_ParseTupleAndKeywords(
-               args, kwds, "|O$O!O!:user_map", (char **)kwlist,
+       static const char *_keywords[] = {"subset", "key_types", "value_types", NULL};
+       static _PyArg_Parser _parser = {"|O$O!O!:user_map", _keywords, 0};
+       if (!_PyArg_ParseTupleAndKeywordsFast(
+               args, kwds, &_parser,
                &subset,
                &PySet_Type, &key_types,
                &PySet_Type, &val_types))
@@ -198,7 +210,7 @@ static PyObject *bpy_user_map(PyObject *UNUSED(self), PyObject *args, PyObject *
                PyObject **subset_array = PySequence_Fast_ITEMS(subset_fast);
                Py_ssize_t subset_len = PySequence_Fast_GET_SIZE(subset_fast);
 
-               data_cb.user_map = PyDict_New();
+               data_cb.user_map = _PyDict_NewPresized(subset_len);
                data_cb.is_subset = true;
                for (; subset_len; subset_array++, subset_len--) {
                        PyObject *set = PySet_New(NULL);
@@ -218,7 +230,6 @@ static PyObject *bpy_user_map(PyObject *UNUSED(self), PyObject *args, PyObject *
        lb_index = set_listbasepointers(bmain, lb_array);
 
        while (lb_index--) {
-
                if (val_types_bitmap && lb_array[lb_index]->first) {
                        if (!id_check_type(lb_array[lb_index]->first, val_types_bitmap)) {
                                continue;
@@ -233,8 +244,26 @@ static PyObject *bpy_user_map(PyObject *UNUSED(self), PyObject *args, PyObject *
                                data_cb.py_id_key_lookup_only = pyrna_id_CreatePyObject(id);
                        }
 
+                       if (!data_cb.is_subset) {
+                               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);
+                               }
+                       }
+
                        data_cb.id_curr = id;
-                       BKE_library_foreach_ID_link(id, foreach_libblock_id_user_map_callback, &data_cb, IDWALK_NOP);
+                       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;