34 #include "../generic/py_capi_rna.h"
35 #include "../generic/py_capi_utils.h"
36 #include "../generic/python_utildefines.h"
60 return (
int)*((
ushort *)&idcode);
74 const int cb_flag = cb_data->
cb_flag;
76 if (
data->types_bitmap) {
97 if ((set = PyDict_GetItem(
data->user_map, key)) ==
NULL) {
99 if (
data->is_subset) {
103 set = PySet_New(
NULL);
104 PyDict_SetItem(
data->user_map, key, set);
113 PySet_Add(set,
data->py_id_curr);
120 ".. method:: user_map(subset, key_types, value_types)\n"
122 " Returns a mapping of all ID data-blocks in current ``bpy.data`` to a set of all "
123 "datablocks using them.\n"
125 " For list of valid set members for key_types & value_types, see: "
126 ":class:`bpy.types.KeyingSetPath.id_type`.\n"
128 " :arg subset: When passed, only these data-blocks and their users will be "
129 "included as keys/values in the map.\n"
130 " :type subset: sequence\n"
131 " :arg key_types: Filter the keys mapped by ID types.\n"
132 " :type key_types: set of strings\n"
133 " :arg value_types: Filter the values in the set by ID types.\n"
134 " :type value_types: set of strings\n"
135 " :return: dictionary of :class:`bpy.types.ID` instances, with sets of ID's as "
149 PyObject *subset =
NULL;
151 PyObject *key_types =
NULL;
152 PyObject *val_types =
NULL;
160 static const char *_keywords[] = {
"subset",
"key_types",
"value_types",
NULL};
161 static _PyArg_Parser _parser = {
170 if (!_PyArg_ParseTupleAndKeywordsFast(
171 args, kwds, &_parser, &subset, &PySet_Type, &key_types, &PySet_Type, &val_types)) {
178 if (key_types_bitmap ==
NULL) {
186 if (val_types_bitmap ==
NULL) {
192 PyObject *subset_fast = PySequence_Fast(subset,
"user_map");
193 if (subset_fast ==
NULL) {
197 PyObject **subset_array = PySequence_Fast_ITEMS(subset_fast);
198 Py_ssize_t subset_len = PySequence_Fast_GET_SIZE(subset_fast);
200 data_cb.
user_map = _PyDict_NewPresized(subset_len);
202 for (; subset_len; subset_array++, subset_len--) {
203 PyObject *set = PySet_New(
NULL);
204 PyDict_SetItem(data_cb.
user_map, *subset_array, set);
207 Py_DECREF(subset_fast);
218 if (key_types_bitmap ==
NULL && val_types_bitmap !=
NULL) {
229 (val_types_bitmap ==
NULL || key_types_bitmap !=
NULL)) {
235 if ((set = PyDict_GetItem(data_cb.
user_map, key)) ==
NULL) {
236 set = PySet_New(
NULL);
237 PyDict_SetItem(data_cb.
user_map, key, set);
263 if (key_types_bitmap !=
NULL) {
267 if (val_types_bitmap !=
NULL) {
275 ".. method:: batch_remove(ids)\n"
277 " Remove (delete) several IDs at once.\n"
279 " WARNING: Considered experimental feature currently.\n"
281 " Note that this function is quicker than individual calls to :func:`remove()` "
282 "(from :class:`bpy.types.BlendData`\n"
283 " ID collections), but less safe/versatile (it can break Blender, e.g. by removing "
286 " :arg ids: Iterables of IDs (types can be mixed).\n"
287 " :type subset: sequence\n");
297 PyObject *ids =
NULL;
301 static const char *_keywords[] = {
"ids",
NULL};
302 static _PyArg_Parser _parser = {
308 if (!_PyArg_ParseTupleAndKeywordsFast(args, kwds, &_parser, &ids)) {
315 PyObject *ids_fast = PySequence_Fast(ids,
"batch_remove");
316 if (ids_fast ==
NULL) {
320 PyObject **ids_array = PySequence_Fast_ITEMS(ids_fast);
321 Py_ssize_t ids_len = PySequence_Fast_GET_SIZE(ids_fast);
323 for (; ids_len; ids_array++, ids_len--) {
327 PyExc_TypeError,
"Expected an ID type, not %.200s", Py_TYPE(*ids_array)->tp_name);
352 ".. method:: orphans_purge()\n"
354 " Remove (delete) all IDs with no user.\n"
356 " :arg do_local_ids: Include unused local IDs in the deletion, defaults to True\n"
357 " :type do_local_ids: bool, optional\n"
358 " :arg do_linked_ids: Include unused linked IDs in the deletion, defaults to True\n"
359 " :type do_linked_ids: bool, optional\n"
360 " :arg do_recursive: Recursively check for unused IDs, ensuring no orphaned one "
361 "remain after a single run of that function, defaults to False\n"
362 " :type do_recursive: bool, optional\n"
363 " :return: The number of deleted IDs.\n");
375 bool do_local_ids =
true;
376 bool do_linked_ids =
true;
377 bool do_recursive_cleanup =
false;
379 static const char *_keywords[] = {
"do_local_ids",
"do_linked_ids",
"do_recursive",
NULL};
380 static _PyArg_Parser _parser = {
389 if (!_PyArg_ParseTupleAndKeywordsFast(args,
397 &do_recursive_cleanup)) {
403 bmain,
LIB_TAG_DOIT, do_local_ids, do_linked_ids, do_recursive_cleanup, num_tagged);
406 return PyLong_FromSize_t(0);
413 return PyLong_FromSize_t(num_datablocks_deleted);
419 METH_STATIC | METH_VARARGS | METH_KEYWORDS,
425 METH_STATIC | METH_VARARGS | METH_KEYWORDS,
426 bpy_batch_remove_doc,
431 METH_STATIC | METH_VARARGS | METH_KEYWORDS,
432 bpy_orphans_purge_doc,
void BKE_main_id_tag_all(struct Main *mainvar, int tag, bool value)
size_t BKE_id_multi_tagged_delete(struct Main *bmain) ATTR_NONNULL()
void BKE_library_foreach_ID_link(struct Main *bmain, struct ID *id, LibraryIDLinkCallback callback, void *user_data, int flag)
void BKE_lib_query_unused_ids_tag(struct Main *bmain, int tag, bool do_local_ids, bool do_linked_ids, bool do_tag_recursive, int *r_num_tagged)
#define FOREACH_MAIN_LISTBASE_ID_END
#define FOREACH_MAIN_LISTBASE_ID_BEGIN(_lb, _id)
#define FOREACH_MAIN_LISTBASE_BEGIN(_bmain, _lb)
#define BLI_BITMAP_TEST_BOOL(_bitmap, _index)
ID and Library types, which are fundamental for sdna.
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
static bool id_check_type(const ID *id, const BLI_bitmap *types_bitmap)
static int id_code_as_index(const short idcode)
static PyObject * bpy_orphans_purge(PyObject *UNUSED(self), PyObject *args, PyObject *kwds)
PyMethodDef BPY_rna_id_collection_batch_remove_method_def
struct IDUserMapData IDUserMapData
static int foreach_libblock_id_user_map_callback(LibraryIDLinkCallbackData *cb_data)
PyDoc_STRVAR(bpy_user_map_doc, ".. method:: user_map(subset, key_types, value_types)\n" "\n" " Returns a mapping of all ID data-blocks in current ``bpy.data`` to a set of all " "datablocks using them.\n" "\n" " For list of valid set members for key_types & value_types, see: " ":class:`bpy.types.KeyingSetPath.id_type`.\n" "\n" " :arg subset: When passed, only these data-blocks and their users will be " "included as keys/values in the map.\n" " :type subset: sequence\n" " :arg key_types: Filter the keys mapped by ID types.\n" " :type key_types: set of strings\n" " :arg value_types: Filter the values in the set by ID types.\n" " :type value_types: set of strings\n" " :return: dictionary of :class:`bpy.types.ID` instances, with sets of ID's as " "their values.\n" " :rtype: dict\n")
PyMethodDef BPY_rna_id_collection_orphans_purge_method_def
static PyObject * bpy_batch_remove(PyObject *UNUSED(self), PyObject *args, PyObject *kwds)
static PyObject * bpy_user_map(PyObject *UNUSED(self), PyObject *args, PyObject *kwds)
PyMethodDef BPY_rna_id_collection_user_map_method_def
PyObject * pyrna_id_CreatePyObject(ID *id)
bool pyrna_id_FromPyObject(PyObject *obj, ID **id)
void(* MEM_freeN)(void *vmemh)
static void error(const char *str)
BLI_bitmap * pyrna_enum_bitmap_from_set(const EnumPropertyItem *items, PyObject *value, int type_size, bool type_convert_sign, int bitmap_size, const char *error_prefix)
int PyC_ParseBool(PyObject *o, void *p)
const EnumPropertyItem rna_enum_id_type_items[]
PyObject_HEAD PointerRNA ptr
BLI_bitmap * types_bitmap
void WM_main_add_notifier(unsigned int type, void *reference)