71 const int cb_flag = cb_data->
cb_flag;
73 if (data->types_bitmap) {
94 if ((set = PyDict_GetItem(data->user_map, key)) ==
nullptr) {
96 if (data->is_subset) {
100 set = PySet_New(
nullptr);
101 PyDict_SetItem(data->user_map, key, set);
106 if (data->py_id_curr ==
nullptr) {
110 PySet_Add(set, data->py_id_curr);
119 ".. method:: user_map(subset, key_types, value_types)\n"
121 " Returns a mapping of all ID data-blocks in current ``bpy.data`` to a set of all "
122 "data-blocks using them.\n"
124 " For list of valid set members for key_types & value_types, see: "
125 ":class:`bpy.types.KeyingSetPath.id_type`.\n"
127 " :arg subset: When passed, only these data-blocks and their users will be "
128 "included as keys/values in the map.\n"
129 " :type subset: Sequence[:class:`bpy.types.ID`]\n"
130 " :arg key_types: Filter the keys mapped by ID types.\n"
131 " :type key_types: set[str]\n"
132 " :arg value_types: Filter the values in the set by ID types.\n"
133 " :type value_types: set[str]\n"
134 " :return: dictionary that maps data-blocks ID's to their users.\n"
135 " :rtype: dict[:class:`bpy.types.ID`, set[:class:`bpy.types.ID`]]\n");
136static PyObject *
bpy_user_map(PyObject * , PyObject *args, PyObject *kwds)
147 PyObject *subset =
nullptr;
149 PyObject *key_types =
nullptr;
150 PyObject *val_types =
nullptr;
154 PyObject *
ret =
nullptr;
158 static const char *_keywords[] = {
"subset",
"key_types",
"value_types",
nullptr};
159 static _PyArg_Parser _parser = {
169 if (!_PyArg_ParseTupleAndKeywordsFast(
170 args, kwds, &_parser, &subset, &PySet_Type, &key_types, &PySet_Type, &val_types))
178 if (key_types_bitmap ==
nullptr) {
186 if (val_types_bitmap ==
nullptr) {
192 PyObject *subset_fast = PySequence_Fast(subset,
"user_map");
193 if (subset_fast ==
nullptr) {
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(
nullptr);
204 PyDict_SetItem(data_cb.
user_map, *subset_array, set);
207 Py_DECREF(subset_fast);
218 if (key_types_bitmap ==
nullptr && val_types_bitmap !=
nullptr) {
226 (key_types_bitmap ==
nullptr ||
id_check_type(
id, key_types_bitmap)) &&
229 (val_types_bitmap ==
nullptr || key_types_bitmap !=
nullptr))
236 if ((set = PyDict_GetItem(data_cb.
user_map, key)) ==
nullptr) {
237 set = PySet_New(
nullptr);
238 PyDict_SetItem(data_cb.
user_map, key, set);
244 if (val_types_bitmap !=
nullptr && !
id_check_type(
id, val_types_bitmap)) {
264 if (key_types_bitmap !=
nullptr) {
268 if (val_types_bitmap !=
nullptr) {
277 bpy_batch_remove_doc,
278 ".. method:: batch_remove(ids)\n"
280 " Remove (delete) several IDs at once.\n"
282 " WARNING: Considered experimental feature currently.\n"
284 " Note that this function is quicker than individual calls to :func:`remove()` "
285 "(from :class:`bpy.types.BlendData`\n"
286 " ID collections), but less safe/versatile (it can break Blender, e.g. by removing "
289 " :arg ids: Sequence of IDs (types can be mixed).\n"
290 " :type ids: Sequence[:class:`bpy.types.ID`]\n");
300 PyObject *ids =
nullptr;
302 PyObject *
ret =
nullptr;
304 static const char *_keywords[] = {
"ids",
nullptr};
305 static _PyArg_Parser _parser = {
312 if (!_PyArg_ParseTupleAndKeywordsFast(args, kwds, &_parser, &ids)) {
319 PyObject *ids_fast = PySequence_Fast(ids,
"batch_remove");
320 if (ids_fast ==
nullptr) {
324 PyObject **ids_array = PySequence_Fast_ITEMS(ids_fast);
325 Py_ssize_t ids_len = PySequence_Fast_GET_SIZE(ids_fast);
327 for (; ids_len; ids_array++, ids_len--) {
331 PyExc_TypeError,
"Expected an ID type, not %.200s", Py_TYPE(*ids_array)->tp_name);
357 bpy_orphans_purge_doc,
358 ".. method:: orphans_purge()\n"
360 " Remove (delete) all IDs with no user.\n"
362 " :arg do_local_ids: Include unused local IDs in the deletion, defaults to True\n"
363 " :type do_local_ids: bool, optional\n"
364 " :arg do_linked_ids: Include unused linked IDs in the deletion, defaults to True\n"
365 " :type do_linked_ids: bool, optional\n"
366 " :arg do_recursive: Recursively check for unused IDs, ensuring no orphaned one "
367 "remain after a single run of that function, defaults to False\n"
368 " :type do_recursive: bool, optional\n"
369 " :return: The number of deleted IDs.\n");
384 static const char *_keywords[] = {
"do_local_ids",
"do_linked_ids",
"do_recursive",
nullptr};
385 static _PyArg_Parser _parser = {
395 if (!_PyArg_ParseTupleAndKeywordsFast(args,
412 return PyLong_FromSize_t(0);
419 return PyLong_FromSize_t(num_datablocks_deleted);
422#if (defined(__GNUC__) && !defined(__clang__))
423# pragma GCC diagnostic push
424# pragma GCC diagnostic ignored "-Wcast-function-type"
430 METH_STATIC | METH_VARARGS | METH_KEYWORDS,
436 METH_STATIC | METH_VARARGS | METH_KEYWORDS,
437 bpy_batch_remove_doc,
442 METH_STATIC | METH_VARARGS | METH_KEYWORDS,
443 bpy_orphans_purge_doc,
446#if (defined(__GNUC__) && !defined(__clang__))
447# pragma GCC diagnostic pop
void size_t BKE_id_multi_tagged_delete(Main *bmain) ATTR_NONNULL()
void BKE_main_id_tag_all(Main *mainvar, int tag, bool value)
void BKE_lib_query_unused_ids_tag(Main *bmain, int tag, LibQueryUnusedIDsData ¶meters)
@ IDWALK_CB_EMBEDDED_NOT_OWNING
void BKE_library_foreach_ID_link(Main *bmain, ID *id, blender::FunctionRef< LibraryIDLinkCallback > callback, void *user_data, int flag)
#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.
Read Guarded memory(de)allocation.
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 " "data-blocks 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[:class:`bpy.types.ID`]\n" " :arg key_types: Filter the keys mapped by ID types.\n" " :type key_types: set[str]\n" " :arg value_types: Filter the values in the set by ID types.\n" " :type value_types: set[str]\n" " :return: dictionary that maps data-blocks ID's to their users.\n" " :rtype: dict[:class:`bpy.types.ID`, set[:class:`bpy.types.ID`]]\n")
static bool id_check_type(const ID *id, const BLI_bitmap *types_bitmap)
static PyObject * bpy_orphans_purge(PyObject *, PyObject *args, PyObject *kwds)
static int id_code_as_index(const short idcode)
PyMethodDef BPY_rna_id_collection_batch_remove_method_def
static int foreach_libblock_id_user_map_callback(LibraryIDLinkCallbackData *cb_data)
PyMethodDef BPY_rna_id_collection_orphans_purge_method_def
static PyObject * bpy_batch_remove(PyObject *, PyObject *args, PyObject *kwds)
PyMethodDef BPY_rna_id_collection_user_map_method_def
static PyObject * bpy_user_map(PyObject *, PyObject *args, PyObject *kwds)
node_ attributes set("label", ss.str())
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
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)
header-only compatibility defines.
#define PY_ARG_PARSER_HEAD_COMPAT()
const EnumPropertyItem rna_enum_id_type_items[]
PyObject_HEAD PointerRNA ptr
BLI_bitmap * types_bitmap
std::array< int, INDEX_ID_MAX > num_total
void WM_main_add_notifier(uint type, void *reference)