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:
Diffstat (limited to 'source/blender/python/intern/bpy_rna_id_collection.c')
-rw-r--r--source/blender/python/intern/bpy_rna_id_collection.c114
1 files changed, 67 insertions, 47 deletions
diff --git a/source/blender/python/intern/bpy_rna_id_collection.c b/source/blender/python/intern/bpy_rna_id_collection.c
index 6ff1849f646..6b6ffa97995 100644
--- a/source/blender/python/intern/bpy_rna_id_collection.c
+++ b/source/blender/python/intern/bpy_rna_id_collection.c
@@ -25,19 +25,19 @@
#include "MEM_guardedalloc.h"
-#include "BLI_utildefines.h"
#include "BLI_bitmap.h"
+#include "BLI_utildefines.h"
#include "BKE_global.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
#include "BKE_main.h"
#include "DNA_ID.h"
/* Those following 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 "DNA_object_types.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -49,16 +49,12 @@
#include "../generic/python_utildefines.h"
#include "RNA_access.h"
-#include "RNA_types.h"
#include "RNA_enum_types.h"
+#include "RNA_types.h"
#include "bpy_rna.h"
typedef struct IDUserMapData {
- /** Place-holder key only used for lookups to avoid creating new data only for lookups
- * (never return its contents) */
- PyObject *py_id_key_lookup_only;
-
/** We loop over data-blocks that this ID points to (do build a reverse lookup table) */
PyObject *py_id_curr;
ID *id_curr;
@@ -74,7 +70,7 @@ typedef struct IDUserMapData {
static int id_code_as_index(const short idcode)
{
- return (int)*((unsigned short *)&idcode);
+ return (int)*((ushort *)&idcode);
}
static bool id_check_type(const ID *id, const BLI_bitmap *types_bitmap)
@@ -82,14 +78,13 @@ static bool id_check_type(const ID *id, const BLI_bitmap *types_bitmap)
return BLI_BITMAP_TEST_BOOL(types_bitmap, id_code_as_index(GS(id->name)));
}
-static int foreach_libblock_id_user_map_callback(void *user_data,
- ID *self_id,
- ID **id_p,
- int UNUSED(cb_flag))
+static int foreach_libblock_id_user_map_callback(LibraryIDLinkCallbackData *cb_data)
{
- IDUserMapData *data = user_data;
+ ID **id_p = cb_data->id_pointer;
if (*id_p) {
+ IDUserMapData *data = cb_data->user_data;
+ const int cb_flag = cb_data->cb_flag;
if (data->types_bitmap) {
if (!id_check_type(*id_p, data->types_bitmap)) {
@@ -97,39 +92,32 @@ static int foreach_libblock_id_user_map_callback(void *user_data,
}
}
- if ((GS(self_id->name) == ID_OB) && (id_p == (ID **)&((Object *)self_id)->proxy_from)) {
- /* We skip proxy_from here,
+ if (cb_flag & IDWALK_CB_LOOPBACK) {
+ /* We skip loop-back pointers like Object.proxy_from or Key.from here,
* since it's some internal pointer which is not relevant 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's some internal pointer which is not relevant info for py/API level. */
+
+ if (cb_flag & IDWALK_CB_EMBEDDED) {
+ /* We skip private pointers themselves, like root node trees, we'll 'link' their own ID
+ * pointers to their 'ID owner' instead. */
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...
- */
- PyObject *key = data->py_id_key_lookup_only;
- RNA_id_pointer_create(*id_p, &((BPy_StructRNA *)key)->ptr);
+ PyObject *key = pyrna_id_CreatePyObject(*id_p);
PyObject *set;
if ((set = PyDict_GetItem(data->user_map, key)) == NULL) {
-
/* limit to key's added already */
if (data->is_subset) {
return IDWALK_RET_NOP;
}
- /* Cannot use our placeholder key here! */
- key = pyrna_id_CreatePyObject(*id_p);
set = PySet_New(NULL);
PyDict_SetItem(data->user_map, key, set);
Py_DECREF(set);
- Py_DECREF(key);
}
+ Py_DECREF(key);
if (data->py_id_curr == NULL) {
data->py_id_curr = pyrna_id_CreatePyObject(data->id_curr);
@@ -238,34 +226,23 @@ static PyObject *bpy_user_map(PyObject *UNUSED(self), PyObject *args, PyObject *
}
}
- /* 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 *key = pyrna_id_CreatePyObject(id);
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);
}
+ Py_DECREF(key);
}
if (val_types_bitmap != NULL && !id_check_type(id, val_types_bitmap)) {
@@ -288,10 +265,6 @@ static PyObject *bpy_user_map(PyObject *UNUSED(self), PyObject *args, PyObject *
ret = data_cb.user_map;
error:
- if (data_cb.py_id_key_lookup_only != NULL) {
- Py_XDECREF(data_cb.py_id_key_lookup_only);
- }
-
if (key_types_bitmap != NULL) {
MEM_freeN(key_types_bitmap);
}
@@ -375,6 +348,43 @@ error:
return ret;
}
+PyDoc_STRVAR(bpy_orphans_purge_doc,
+ ".. method:: orphans_purge()\n"
+ "\n"
+ " Remove (delete) all IDs with no user.\n"
+ "\n"
+ " WARNING: Considered experimental feature currently.\n");
+static PyObject *bpy_orphans_purge(PyObject *UNUSED(self),
+ PyObject *UNUSED(args),
+ PyObject *UNUSED(kwds))
+{
+#if 0 /* If someone knows how to get a proper 'self' in that case... */
+ BPy_StructRNA *pyrna = (BPy_StructRNA *)self;
+ Main *bmain = pyrna->ptr.data;
+#else
+ Main *bmain = G_MAIN; /* XXX Ugly, but should work! */
+#endif
+
+ ID *id;
+ FOREACH_MAIN_ID_BEGIN (bmain, id) {
+ if (id->us == 0) {
+ id->tag |= LIB_TAG_DOIT;
+ }
+ else {
+ id->tag &= ~LIB_TAG_DOIT;
+ }
+ }
+ FOREACH_MAIN_ID_END;
+
+ BKE_id_multi_tagged_delete(bmain);
+ /* Force full redraw, mandatory to avoid crashes when running this from UI... */
+ WM_main_add_notifier(NC_WINDOW, NULL);
+
+ Py_INCREF(Py_None);
+
+ return Py_None;
+}
+
int BPY_rna_id_collection_module(PyObject *mod_par)
{
static PyMethodDef user_map = {
@@ -392,5 +402,15 @@ int BPY_rna_id_collection_module(PyObject *mod_par)
PyModule_AddObject(
mod_par, "_rna_id_collection_batch_remove", PyCFunction_New(&batch_remove, NULL));
+ static PyMethodDef orphans_purge = {
+ "orphans_purge",
+ (PyCFunction)bpy_orphans_purge,
+ METH_VARARGS | METH_KEYWORDS,
+ bpy_orphans_purge_doc,
+ };
+
+ PyModule_AddObject(
+ mod_par, "_rna_id_collection_orphans_purge", PyCFunction_New(&orphans_purge, NULL));
+
return 0;
}