Blender V5.0
lib_id.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11
12#include <cctype>
13#include <cstddef>
14#include <cstdio>
15#include <cstdlib>
16#include <cstring>
17#include <optional>
18
19#include "CLG_log.h"
20
21#include "MEM_guardedalloc.h"
22
23/* all types are needed here, in order to do memory operations */
24#include "DNA_ID.h"
25#include "DNA_anim_types.h"
27#include "DNA_key_types.h"
28#include "DNA_node_types.h"
29#include "DNA_workspace_types.h"
30
31#include "BLI_listbase.h"
32#include "BLI_utildefines.h"
33
34#include "BLI_ghash.h"
35#include "BLI_linklist.h"
36#include "BLI_memarena.h"
37#include "BLI_path_utils.hh"
38#include "BLI_string.h"
39#include "BLI_string_ref.hh"
40#include "BLI_string_utf8.h"
41#include "BLI_string_utils.hh"
42
43#include "BLT_translation.hh"
44
45#include "BKE_anim_data.hh"
46#include "BKE_armature.hh"
47#include "BKE_asset.hh"
48#include "BKE_bpath.hh"
49#include "BKE_context.hh"
50#include "BKE_global.hh"
51#include "BKE_idprop.hh"
52#include "BKE_idtype.hh"
53#include "BKE_key.hh"
54#include "BKE_lib_id.hh"
55#include "BKE_lib_override.hh"
56#include "BKE_lib_query.hh"
57#include "BKE_lib_remap.hh"
58#include "BKE_library.hh"
59#include "BKE_main.hh"
60#include "BKE_main_namemap.hh"
61#include "BKE_node.hh"
62#include "BKE_rigidbody.h"
63
64#include "DEG_depsgraph.hh"
67
68#include "RNA_access.hh"
69
70#include "BLO_read_write.hh"
71
72#include "atomic_ops.h"
73
74#include "lib_intern.hh"
75
76// #define DEBUG_TIME
77
78#ifdef DEBUG_TIME
79# include "BLI_time_utildefines.h"
80#endif
81
82using blender::Vector;
83
84using namespace blender::bke::id;
85
86static CLG_LogRef LOG = {"lib.id"};
87
89 /*id_code*/ ID_LINK_PLACEHOLDER,
90 /*id_filter*/ 0,
91 /*dependencies_id_types*/ 0,
92 /*main_listbase_index*/ INDEX_ID_NULL,
93 /*struct_size*/ sizeof(ID),
94 /*name*/ "LinkPlaceholder",
95 /*name_plural*/ N_("link_placeholders"),
96 /*translation_context*/ BLT_I18NCONTEXT_ID_ID,
98 /*asset_type_info*/ nullptr,
99
100 /*init_data*/ nullptr,
101 /*copy_data*/ nullptr,
102 /*free_data*/ nullptr,
103 /*make_local*/ nullptr,
104 /*foreach_id*/ nullptr,
105 /*foreach_cache*/ nullptr,
106 /*foreach_path*/ nullptr,
107 /*foreach_working_space_color*/ nullptr,
108 /*owner_pointer_get*/ nullptr,
109
110 /*blend_write*/ nullptr,
111 /*blend_read_data*/ nullptr,
112 /*blend_read_after_liblink*/ nullptr,
113
114 /*blend_read_undo_preserve*/ nullptr,
115
116 /*lib_override_apply_post*/ nullptr,
117};
118
119/* GS reads the memory pointed at in a specific ordering.
120 * only use this definition, makes little and big endian systems
121 * work fine, in conjunction with MAKE_ID */
122
123/* ************* general ************************ */
124
130 char *path_dst,
131 size_t path_dst_maxncpy,
132 const char *path_src)
133{
134 const char **data = static_cast<const char **>(bpath_data->user_data);
135 /* be sure there is low chance of the path being too short */
136 char filepath[(FILE_MAXDIR * 2) + FILE_MAXFILE];
137 const char *base_new = data[0];
138 const char *base_old = data[1];
139
140 if (BLI_path_is_rel(base_old)) {
141 CLOG_ERROR(&LOG, "old base path '%s' is not absolute.", base_old);
142 return false;
143 }
144
145 /* Make referenced file absolute. This would be a side-effect of
146 * BLI_path_normalize, but we do it explicitly so we know if it changed. */
147 BLI_strncpy(filepath, path_src, FILE_MAX);
148 if (BLI_path_abs(filepath, base_old)) {
149 /* Path was relative and is now absolute. Remap.
150 * Important BLI_path_normalize runs before the path is made relative
151 * because it won't work for paths that start with `//../` */
152 BLI_path_normalize(filepath);
153 BLI_path_rel(filepath, base_new);
154 BLI_strncpy(path_dst, filepath, path_dst_maxncpy);
155 return true;
156 }
157
158 /* Path was not relative to begin with. */
159 return false;
160}
161
179static void lib_id_library_local_paths(Main *bmain, Library *lib_to, Library *lib_from, ID *id)
180{
181 BLI_assert(lib_to || lib_from);
182 const char *bpath_user_data[2] = {
183 lib_to ? lib_to->runtime->filepath_abs : BKE_main_blendfile_path(bmain),
184 lib_from ? lib_from->runtime->filepath_abs : BKE_main_blendfile_path(bmain)};
185
186 BPathForeachPathData path_data{};
187 path_data.bmain = bmain;
190 path_data.user_data = (void *)bpath_user_data;
191 BKE_bpath_foreach_path_id(&path_data, id);
192}
193
194static int lib_id_clear_library_data_users_update_cb(LibraryIDLinkCallbackData *cb_data)
195{
196 ID *id = static_cast<ID *>(cb_data->user_data);
197 if (*cb_data->id_pointer == id) {
198 /* Even though the ID itself remain the same after being made local, from depsgraph point of
199 * view this is a different ID. Hence we need to tag all of its users for a copy-on-eval
200 * update. */
204 }
206}
207
208void BKE_lib_id_clear_library_data(Main *bmain, ID *id, const int flags)
209{
210 const bool id_in_mainlist = (id->tag & ID_TAG_NO_MAIN) == 0 &&
211 (id->flag & ID_FLAG_EMBEDDED_DATA) == 0;
212
213 if (id_in_mainlist) {
214 BKE_main_namemap_remove_id(*bmain, *id);
215 }
216
217 lib_id_library_local_paths(bmain, nullptr, id->lib, id);
218
220
221 id->lib = nullptr;
222 id->tag &= ~(ID_TAG_INDIRECT | ID_TAG_EXTERN);
224 if (id_in_mainlist) {
226 *which_libbase(bmain, GS(id->name)),
227 *id,
228 nullptr,
230 false);
231 if (!ELEM(result.action,
234 {
235 bmain->is_memfile_undo_written = false;
236 }
237 }
238
239 /* Conceptually, an ID made local is not the same as the linked one anymore. Reflect that by
240 * regenerating its session UID. */
241 if ((id->tag & ID_TAG_TEMP_MAIN) == 0) {
243 }
244
245 if (ID_IS_ASSET(id)) {
246 if ((flags & LIB_ID_MAKELOCAL_ASSET_DATA_CLEAR) != 0) {
247 const IDTypeInfo *idtype_info = BKE_idtype_get_info_from_id(id);
248 if (idtype_info && idtype_info->asset_type_info &&
250 {
251 idtype_info->asset_type_info->on_clear_asset_fn(id, id->asset_data);
252 }
253 BKE_asset_metadata_free(&id->asset_data);
254 }
255 else {
256 /* Assets should always have a fake user. Ensure this is the case after "Make Local". */
258 }
259 }
260
261 /* Ensure that the deephash is reset when making an ID local (in case it was previously a packed
262 * linked ID), as this is by definition not a valid deephash anymore (that ID is now a fully
263 * independent copy living in another blendfile). */
264 id->deep_hash = {};
265
266 /* We need to tag this IDs and all of its users, conceptually new local ID and original linked
267 * ones are two completely different data-blocks that were virtually remapped, even though in
268 * reality they remain the same data. For undo this info is critical now. */
270 ID *id_iter;
271 FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
273 bmain, id_iter, lib_id_clear_library_data_users_update_cb, id, IDWALK_READONLY);
274 }
276
277 /* Internal shape key blocks inside data-blocks also stores id->lib,
278 * make sure this stays in sync (note that we do not need any explicit handling for real EMBEDDED
279 * IDs here, this is down automatically in `lib_id_expand_local_cb()`. */
280 Key *key = BKE_key_from_id(id);
281 if (key != nullptr) {
282 BKE_lib_id_clear_library_data(bmain, &key->id, flags);
283 }
284
285 /* Even though the ID itself remain the same after being made local, from depsgraph point of view
286 * this is a different ID. Hence we rebuild depsgraph relationships. */
288}
289
291{
292 if (id && ID_IS_LINKED(id)) {
294 if (id->tag & ID_TAG_INDIRECT) {
295 id->tag &= ~ID_TAG_INDIRECT;
296 id->flag &= ~ID_FLAG_INDIRECT_WEAK_LINK;
297 id->tag |= ID_TAG_EXTERN;
298 id->lib->runtime->parent = nullptr;
299 }
300 }
301}
302
304{
305 if (id && ID_IS_LINKED(id)) {
307 if (id->tag & ID_TAG_INDIRECT) {
308 id->flag |= ID_FLAG_INDIRECT_WEAK_LINK;
309 }
310 }
311}
312
314{
315 if (id) {
316 const int limit = ID_FAKE_USERS(id);
317 id->tag |= ID_TAG_EXTRAUSER;
318 if (id->us <= limit) {
319 if (id->us < limit || ((id->us == limit) && (id->tag & ID_TAG_EXTRAUSER_SET))) {
321 "ID user count error: %s (from '%s')",
322 id->name,
323 id->lib ? id->lib->runtime->filepath_abs : "[Main]");
324 }
325 id->us = limit + 1;
326 id->tag |= ID_TAG_EXTRAUSER_SET;
327 }
328 }
329}
330
332{
333 if (id && (id->tag & ID_TAG_EXTRAUSER)) {
334 if (id->tag & ID_TAG_EXTRAUSER_SET) {
335 id->us--;
336 BLI_assert(id->us >= ID_FAKE_USERS(id));
337 }
339 }
340}
341
343{
344 if (id) {
345 if ((id->tag & ID_TAG_EXTRAUSER) && (id->tag & ID_TAG_EXTRAUSER_SET)) {
346 BLI_assert(id->us >= 1);
347 /* No need to increase count, just tag extra user as no more set.
348 * Avoids annoying & inconsistent +1 in user count. */
349 id->tag &= ~ID_TAG_EXTRAUSER_SET;
350 }
351 else {
352 BLI_assert(id->us >= 0);
353 id->us++;
354 }
355 }
356}
357
358void id_us_plus(ID *id)
359{
360 if (id) {
362 id_lib_extern(id);
363 }
364}
365
366void id_us_min(ID *id)
367{
368 if (id) {
369 const int limit = ID_FAKE_USERS(id);
370
371 if (id->us <= limit) {
372 if (!ID_TYPE_IS_DEPRECATED(GS(id->name))) {
373 /* Do not assert on deprecated ID types, we cannot really ensure that their ID
374 * reference-counting is valid. */
376 "ID user decrement error: %s (from '%s'): %d <= %d",
377 id->name,
378 id->lib ? id->lib->runtime->filepath_abs : "[Main]",
379 id->us,
380 limit);
381 }
382 id->us = limit;
383 }
384 else {
385 id->us--;
386 }
387
388 if ((id->us == limit) && (id->tag & ID_TAG_EXTRAUSER)) {
389 /* We need an extra user here, but never actually incremented user count for it so far,
390 * do it now. */
392 }
393 }
394}
395
397{
398 if (id && !(id->flag & ID_FLAG_FAKEUSER)) {
399 id->flag |= ID_FLAG_FAKEUSER;
400 id_us_plus(id);
401 }
402}
403
405{
406 if (id && (id->flag & ID_FLAG_FAKEUSER)) {
407 id->flag &= ~ID_FLAG_FAKEUSER;
408 id_us_min(id);
409 }
410}
411
413{
414 /* We assume that if this ID has no new ID, its embedded data has not either. */
415 if (id->newid == nullptr) {
416 return;
417 }
418
419 id->newid->tag &= ~ID_TAG_NEW;
420 id->newid = nullptr;
421
422 /* Deal with embedded data too. */
423 /* NOTE: even though ShapeKeys are not technically embedded data currently, they behave as such
424 * in most cases, so for sake of consistency treat them as such here. Also mirrors the behavior
425 * in `BKE_lib_id_make_local`. */
426 Key *key = BKE_key_from_id(id);
427 if (key != nullptr) {
429 }
431 if (ntree != nullptr) {
433 }
434 if (GS(id->name) == ID_SCE) {
435 Collection *master_collection = ((Scene *)id)->master_collection;
436 if (master_collection != nullptr) {
437 BKE_id_newptr_and_tag_clear(&master_collection->id);
438 }
439 }
440}
441
443{
444 Main *bmain = cb_data->bmain;
445 ID *self_id = cb_data->self_id;
446 ID **id_pointer = cb_data->id_pointer;
447 int const cb_flag = cb_data->cb_flag;
448 const int flags = POINTER_AS_INT(cb_data->user_data);
449
450 if (cb_flag & IDWALK_CB_LOOPBACK) {
451 /* We should never have anything to do with loop-back pointers here. */
452 return IDWALK_RET_NOP;
453 }
454
456 /* Embedded data-blocks need to be made fully local as well.
457 * Note however that in some cases (when owner ID had to be duplicated instead of being made
458 * local directly), its embedded IDs should also have already been duplicated, and hence be
459 * fully local here already. */
460 if (*id_pointer != nullptr && ID_IS_LINKED(*id_pointer)) {
461 BLI_assert(*id_pointer != self_id);
462
463 BKE_lib_id_clear_library_data(bmain, *id_pointer, flags);
464 }
465 return IDWALK_RET_NOP;
466 }
467
468 /* Can happen that we get un-linkable ID here, e.g. with shape-key referring to itself
469 * (through drivers)...
470 * Just skip it, shape key can only be either indirectly linked, or fully local, period.
471 * And let's curse one more time that stupid useless shape-key ID type! */
472 if (*id_pointer && *id_pointer != self_id &&
473 BKE_idtype_idcode_is_linkable(GS((*id_pointer)->name)))
474 {
475 id_lib_extern(*id_pointer);
476 }
477
478 return IDWALK_RET_NOP;
479}
480
481void BKE_lib_id_expand_local(Main *bmain, ID *id, const int flags)
482{
485}
486
487void lib_id_copy_ensure_local(Main *bmain, const ID *old_id, ID *new_id, const int flags)
488{
489 if (ID_IS_LINKED(old_id)) {
490 /* For packed linked data copied into local IDs in Main, assume that they are no more related
491 * to their original library source, and clear their deephash.
492 *
493 * NOTE: In case more control is needed over that behavior in the future, a new flag can be
494 * added instead. */
495 new_id->deep_hash = {};
496
497 BKE_lib_id_expand_local(bmain, new_id, flags);
498 lib_id_library_local_paths(bmain, nullptr, old_id->lib, new_id);
499 }
500}
501
503 Main *bmain, ID *id, int flags, bool *r_force_local, bool *r_force_copy)
504{
505 bool force_local = (flags & LIB_ID_MAKELOCAL_FORCE_LOCAL) != 0;
506 bool force_copy = (flags & LIB_ID_MAKELOCAL_FORCE_COPY) != 0;
507 BLI_assert(force_copy == false || force_copy != force_local);
508
509 if (force_local || force_copy) {
510 /* Already set by caller code, nothing to do here. */
511 *r_force_local = force_local;
512 *r_force_copy = force_copy;
513 return;
514 }
515
516 const bool lib_local = (flags & LIB_ID_MAKELOCAL_FULL_LIBRARY) != 0;
517 bool is_local = false, is_lib = false;
518
519 /* - no user (neither lib nor local): make local (happens e.g. with UI-used only data).
520 * - only lib users: do nothing (unless force_local is set)
521 * - only local users: make local
522 * - mixed: make copy
523 * In case we make a whole lib's content local,
524 * we always want to localize, and we skip remapping (done later).
525 */
526
527 BKE_library_ID_test_usages(bmain, id, &is_local, &is_lib);
528 if (!lib_local && !is_local && !is_lib) {
529 force_local = true;
530 }
531 else if (lib_local || is_local) {
532 if (!is_lib) {
533 force_local = true;
534 }
535 else {
536 force_copy = true;
537 }
538 }
539
540 *r_force_local = force_local;
541 *r_force_copy = force_copy;
542}
543
544void BKE_lib_id_make_local_generic(Main *bmain, ID *id, const int flags)
545{
546 if (!ID_IS_LINKED(id)) {
547 return;
548 }
549
550 bool force_local, force_copy;
551 BKE_lib_id_make_local_generic_action_define(bmain, id, flags, &force_local, &force_copy);
552
553 if (force_local) {
554 BKE_lib_id_clear_library_data(bmain, id, flags);
555 if ((flags & LIB_ID_MAKELOCAL_LIBOVERRIDE_CLEAR) != 0) {
557 }
558 BKE_lib_id_expand_local(bmain, id, flags);
559 }
560 else if (force_copy) {
561 const int copy_flags =
564 ID *id_new = BKE_id_copy_ex(bmain, id, nullptr, copy_flags);
565
566 /* Should not fail in expected use cases,
567 * but a few ID types cannot be copied (LIB, WM, SCR...). */
568 if (id_new != nullptr) {
569 id_new->us = 0;
570
571 /* setting newid is mandatory for complex make_lib_local logic... */
572 ID_NEW_SET(id, id_new);
573 Key *key = BKE_key_from_id(id), *key_new = BKE_key_from_id(id);
574 if (key && key_new) {
575 ID_NEW_SET(key, key_new);
576 }
578 *ntree_new = blender::bke::node_tree_from_id(id_new);
579 if (ntree && ntree_new) {
580 ID_NEW_SET(ntree, ntree_new);
581 }
582 if (GS(id->name) == ID_SCE) {
583 Collection *master_collection = ((Scene *)id)->master_collection,
584 *master_collection_new = ((Scene *)id_new)->master_collection;
585 if (master_collection && master_collection_new) {
586 ID_NEW_SET(master_collection, master_collection_new);
587 }
588 }
589
590 const bool lib_local = (flags & LIB_ID_MAKELOCAL_FULL_LIBRARY) != 0;
591 if (!lib_local) {
593 }
594 }
595 }
596}
597
598bool BKE_lib_id_make_local(Main *bmain, ID *id, const int flags)
599{
600 const bool lib_local = (flags & LIB_ID_MAKELOCAL_FULL_LIBRARY) != 0;
601
602 /* Skip indirectly linked IDs, unless the whole library is made local, or handling them is
603 * explicitly requested. */
604 if (!(lib_local || (flags & LIB_ID_MAKELOCAL_INDIRECT) != 0) && (id->tag & ID_TAG_INDIRECT)) {
605 return false;
606 }
607
608 const IDTypeInfo *idtype_info = BKE_idtype_get_info_from_id(id);
609
610 if (idtype_info == nullptr) {
611 BLI_assert_msg(0, "IDType Missing IDTypeInfo");
612 return false;
613 }
614
615 BLI_assert((idtype_info->flags & IDTYPE_FLAGS_NO_LIBLINKING) == 0);
616
617 if (idtype_info->make_local != nullptr) {
618 idtype_info->make_local(bmain, id, flags);
619 }
620 else {
621 BKE_lib_id_make_local_generic(bmain, id, flags);
622 }
623
624 return true;
625}
626
632
635{
636 ID **id_pointer = cb_data->id_pointer;
637 ID *id = *id_pointer;
638 const LibraryForeachIDCallbackFlag cb_flag = cb_data->cb_flag;
640
641 /* Remap self-references to new copied ID. */
642 if (id == data->id_src) {
643 /* We cannot use self_id here, it is not *always* id_dst (thanks to confounded node-trees!). */
644 id = *id_pointer = data->id_dst;
645 }
646
647 /* Increase used IDs refcount if needed and required. */
648 if ((data->flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0 && (cb_flag & IDWALK_CB_USER)) {
649 if ((data->flag & LIB_ID_CREATE_NO_MAIN) != 0) {
652 }
653 else if (ID_IS_LINKED(cb_data->owner_id)) {
654 /* Do not mark copied ID as directly linked, if its current user is also linked data (which
655 * is now fairly common when using 'copy_in_lib' feature). */
657 }
658 else {
659 id_us_plus(id);
660 }
661 }
662
663 return IDWALK_RET_NOP;
664}
665
667{
668#define LIB_ID_TYPES_NOCOPY ID_LI, ID_SCR, ID_WM, ID_WS /* Not supported */
669
670 return !ID_TYPE_IS_DEPRECATED(GS(id->name)) && !ELEM(GS(id->name), LIB_ID_TYPES_NOCOPY);
671
672#undef LIB_ID_TYPES_NOCOPY
673}
674
676 std::optional<Library *> owner_library,
677 const ID *id,
678 std::optional<const ID *> new_owner_id,
679 ID **new_id_p,
680 const int flag)
681{
682 ID *newid = (new_id_p != nullptr) ? *new_id_p : nullptr;
684 "Copying with 'no allocate' behavior should always get a non-null new ID buffer");
685
686 /* Make sure destination pointer is all good. */
687 if ((flag & LIB_ID_CREATE_NO_ALLOCATE) == 0) {
688 newid = nullptr;
689 }
690 else {
691 if (!newid) {
692 /* Invalid case, already caught by the assert above. */
693 return nullptr;
694 }
695 }
696
697 /* Early output if source is nullptr. */
698 if (id == nullptr) {
699 return nullptr;
700 }
701
702 const IDTypeInfo *idtype_info = BKE_idtype_get_info_from_id(id);
703
704 if (idtype_info != nullptr) {
705 if ((idtype_info->flags & IDTYPE_FLAGS_NO_COPY) != 0) {
706 return nullptr;
707 }
708
709 BKE_libblock_copy_in_lib(bmain, owner_library, id, new_owner_id, &newid, flag);
710
711 if (idtype_info->copy_data != nullptr) {
712 idtype_info->copy_data(bmain, owner_library, newid, id, flag);
713 }
714 }
715 else {
716 BLI_assert_msg(0, "IDType Missing IDTypeInfo");
717 }
718
719 BLI_assert_msg(newid, "Could not get an allocated new ID to copy into");
720 if (!newid) {
721 return nullptr;
722 }
723
724 /* Update ID refcount, remap pointers to self in new ID. */
726 data.id_src = id;
727 data.id_dst = newid;
728 data.flag = flag;
729 /* When copying an embedded ID, typically at this point its owner ID pointer will still point to
730 * the owner of the source, this code has no access to its valid (i.e. destination) owner. This
731 * can be added at some point if needed, but currently the #id_copy_libmanagement_cb callback
732 * does need this information. */
735
736 /* FIXME: Check if this code can be moved in #BKE_libblock_copy_in_lib ? Would feel more fitted
737 * there, having library handling split between both functions does not look good. */
738 /* Do not make new copy local in case we are copying outside of main...
739 * XXX TODO: is this behavior OK, or should we need a separate flag to control that? */
740 if ((flag & LIB_ID_CREATE_NO_MAIN) == 0) {
741 BLI_assert(!owner_library || newid->lib == *owner_library);
742 /* If the ID was copied into a library, ensure paths are properly remapped, and that it has a
743 * 'linked' tag set. */
744 if (ID_IS_LINKED(newid)) {
745 if (newid->lib != id->lib) {
746 lib_id_library_local_paths(bmain, newid->lib, id->lib, newid);
747 }
748 if ((newid->tag & (ID_TAG_EXTERN | ID_TAG_INDIRECT)) == 0) {
749 newid->tag |= ID_TAG_EXTERN;
750 }
751 }
752 /* Expanding local linked ID usages should never be needed with embedded IDs - this will be
753 * handled together with their owner ID copying code. */
754 else if ((newid->flag & ID_FLAG_EMBEDDED_DATA) == 0) {
755 lib_id_copy_ensure_local(bmain, id, newid, 0);
756 }
757 }
758
759 else {
760 /* NOTE: Do not call `ensure_local` for IDs copied outside of Main, even if they do become
761 * local.
762 *
763 * Most of the time, this would not be the desired behavior currently.
764 *
765 * In the few cases where this is actually needed (e.g. from liboverride resync code, see
766 * #lib_override_library_create_from), calling code is responsible for this. */
767 newid->lib = owner_library ? *owner_library : id->lib;
768 }
769
770 if (new_id_p != nullptr) {
771 *new_id_p = newid;
772 }
773
774 return newid;
775}
776
777ID *BKE_id_copy_ex(Main *bmain, const ID *id, ID **new_id_p, const int flag)
778{
779 return BKE_id_copy_in_lib(bmain, std::nullopt, id, std::nullopt, new_id_p, flag);
780}
781
782ID *BKE_id_copy(Main *bmain, const ID *id)
783{
784 return BKE_id_copy_in_lib(bmain, std::nullopt, id, std::nullopt, nullptr, LIB_ID_COPY_DEFAULT);
785}
786
788 ID *id,
789 const eDupli_ID_Flags duplicate_flags,
790 const int copy_flags)
791{
792 if (id == nullptr) {
793 return id;
794 }
795 if (id->newid == nullptr) {
796 const bool do_linked_id = (duplicate_flags & USER_DUP_LINKED_ID) != 0;
797 if (!(do_linked_id || !ID_IS_LINKED(id))) {
798 return id;
799 }
800
801 ID *id_new = BKE_id_copy_ex(bmain, id, nullptr, copy_flags);
802 /* Copying add one user by default, need to get rid of that one. */
803 id_us_min(id_new);
804 ID_NEW_SET(id, id_new);
805
806 /* Shape keys are always copied with their owner ID, by default. */
807 ID *key_new = (ID *)BKE_key_from_id(id_new);
808 ID *key = (ID *)BKE_key_from_id(id);
809 if (key != nullptr) {
810 ID_NEW_SET(key, key_new);
811 }
812
813 /* NOTE: embedded data (root node-trees and master collections) should never be referenced by
814 * anything else, so we do not need to set their newid pointer and flag. */
815
816 BKE_animdata_duplicate_id_action(bmain, id_new, duplicate_flags);
817 if (key_new != nullptr) {
818 BKE_animdata_duplicate_id_action(bmain, key_new, duplicate_flags);
819 }
820 /* Note that actions of embedded data (root node-trees and master collections) are handled
821 * by #BKE_animdata_duplicate_id_action as well. */
822 }
823 return id->newid;
824}
825
827{
828 ID **id_p = cb_data->id_pointer;
829
830 if (*id_p) {
831 ID *id = *id_p;
832 *id_p = DEG_get_original(id);
833
834 /* If the ID changes increase the user count.
835 *
836 * This means that the reference to evaluated ID has been changed with a reference to the
837 * original ID which implies that the user count of the original ID is increased.
838 *
839 * The evaluated IDs do not maintain their user counter, so do not change it to avoid issues
840 * with the user counter going negative. */
841 if (*id_p != id) {
842 if ((cb_data->cb_flag & IDWALK_CB_USER) != 0) {
843 id_us_plus(*id_p);
844 }
845 }
846 }
847
848 return IDWALK_RET_NOP;
849}
850
852{
853 ID *newid = BKE_id_copy(bmain, id);
854
855 if (newid == nullptr) {
856 return newid;
857 }
858
859 /* Assign ID references directly used by the given ID to their original complementary parts.
860 *
861 * For example, when is called on an evaluated object will assign object->data to its original
862 * pointer, the evaluated object->data will be kept unchanged. */
864 nullptr, newid, foreach_assign_id_to_orig_callback, nullptr, IDWALK_NOP);
865
866 /* Shape keys reference on evaluated ID is preserved to keep driver paths available, but the key
867 * data is likely to be invalid now due to modifiers, so clear the shape key reference avoiding
868 * any possible shape corruption. */
869 if (DEG_is_evaluated(id)) {
870 Key **key_p = BKE_key_from_id_p(newid);
871 if (key_p) {
872 *key_p = nullptr;
873 }
874 }
875
876 return newid;
877}
878
879void BKE_id_move_to_same_lib(Main &bmain, ID &id, const ID &owner_id)
880{
881 if (owner_id.lib == id.lib) {
882 /* `id` is already in the target library, nothing to do. */
883 return;
884 }
885 if (ID_IS_LINKED(&id)) {
886 BLI_assert_msg(false, "Only local IDs can be moved into a library");
887 /* Protect release builds against errors in calling code, as continuing here can lead to
888 * critical Main data-base corruption. */
889 return;
890 }
891
893
894 id.lib = owner_id.lib;
895 id.tag |= ID_TAG_INDIRECT;
896
897 ListBase &lb = *which_libbase(&bmain, GS(id.name));
899 bmain, lb, id, BKE_id_name(id), IDNewNameMode::RenameExistingNever, true);
900}
901
902static void id_embedded_swap(Main *bmain,
903 ID **embedded_id_a,
904 ID **embedded_id_b,
905 const bool do_full_id,
906 IDRemapper *remapper_id_a,
907 IDRemapper *remapper_id_b);
908
913static void id_swap(Main *bmain,
914 ID *id_a,
915 ID *id_b,
916 const bool do_full_id,
917 const bool do_self_remap,
918 IDRemapper *input_remapper_id_a,
919 IDRemapper *input_remapper_id_b,
920 const int self_remap_flags)
921{
922 BLI_assert(GS(id_a->name) == GS(id_b->name));
923
924 IDRemapper *remapper_id_a = input_remapper_id_a;
925 IDRemapper *remapper_id_b = input_remapper_id_b;
926 if (do_self_remap) {
927 if (remapper_id_a == nullptr) {
928 remapper_id_a = MEM_new<IDRemapper>(__func__);
929 }
930 if (remapper_id_b == nullptr) {
931 remapper_id_b = MEM_new<IDRemapper>(__func__);
932 }
933 }
934
935 const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id_a);
936 BLI_assert(id_type != nullptr);
937 const size_t id_struct_size = id_type->struct_size;
938
939 const ID id_a_back = *id_a;
940 const ID id_b_back = *id_b;
941
942 char *id_swap_buff = static_cast<char *>(alloca(id_struct_size));
943
944 memcpy(id_swap_buff, id_a, id_struct_size);
945 memcpy(id_a, id_b, id_struct_size);
946 memcpy(id_b, id_swap_buff, id_struct_size);
947
948 if (!do_full_id) {
949 /* Restore original ID's internal data. */
950 *id_a = id_a_back;
951 *id_b = id_b_back;
952
953 /* Exception: IDProperties. */
954 id_a->properties = id_b_back.properties;
955 id_b->properties = id_a_back.properties;
956 id_a->system_properties = id_b_back.system_properties;
957 id_b->system_properties = id_a_back.system_properties;
958 /* Exception: recalc flags. */
959 id_a->recalc = id_b_back.recalc;
960 id_b->recalc = id_a_back.recalc;
961 }
962
963 id_embedded_swap(bmain,
966 do_full_id,
967 remapper_id_a,
968 remapper_id_b);
969 if (GS(id_a->name) == ID_SCE) {
970 Scene *scene_a = (Scene *)id_a;
971 Scene *scene_b = (Scene *)id_b;
972 id_embedded_swap(bmain,
973 (ID **)&scene_a->master_collection,
974 (ID **)&scene_b->master_collection,
975 do_full_id,
976 remapper_id_a,
977 remapper_id_b);
978 }
979
980 if (remapper_id_a != nullptr) {
981 remapper_id_a->add(id_b, id_a);
982 }
983 if (remapper_id_b != nullptr) {
984 remapper_id_b->add(id_a, id_b);
985 }
986
987 /* Finalize remapping of internal references to self broken by swapping, if requested. */
988 if (do_self_remap) {
990 bmain, {id_a}, ID_REMAP_TYPE_REMAP, *remapper_id_a, self_remap_flags);
992 bmain, {id_b}, ID_REMAP_TYPE_REMAP, *remapper_id_b, self_remap_flags);
993 }
994
995 if ((id_type->flags & IDTYPE_FLAGS_NO_ANIMDATA) == 0 && bmain) {
996 /* Action Slots point to the IDs they animate, and thus now also needs swapping. Instead of
997 * doing this here (and requiring knowledge of how that's supposed to be done), just mark these
998 * pointers as dirty so that they're rebuilt at first use.
999 *
1000 * There are a few calls to id_swap() where `bmain` is nil. None of these matter here, though:
1001 *
1002 * - At blendfile load (`read_libblock_undo_restore_at_old_address()`). Fine
1003 * because after loading the action slot user cache is rebuilt anyway.
1004 * - Swapping window managers (`swap_wm_data_for_blendfile()`). Fine because
1005 * WMs cannot be animated.
1006 * - Palette undo code (`palette_undo_preserve()`). Fine because palettes
1007 * cannot be animated. */
1009 }
1010
1011 if (input_remapper_id_a == nullptr && remapper_id_a != nullptr) {
1012 MEM_delete(remapper_id_a);
1013 }
1014 if (input_remapper_id_b == nullptr && remapper_id_b != nullptr) {
1015 MEM_delete(remapper_id_b);
1016 }
1017}
1018
1019/* Conceptually, embedded IDs are part of their owner's data. However, some parts of the code
1020 * (like e.g. the depsgraph) may treat them as independent IDs, so swapping them here and
1021 * switching their pointers in the owner IDs allows to help not break cached relationships and
1022 * such (by preserving the pointer values). */
1023static void id_embedded_swap(Main *bmain,
1024 ID **embedded_id_a,
1025 ID **embedded_id_b,
1026 const bool do_full_id,
1027 IDRemapper *remapper_id_a,
1028 IDRemapper *remapper_id_b)
1029{
1030 if (embedded_id_a != nullptr && *embedded_id_a != nullptr) {
1031 BLI_assert(embedded_id_b != nullptr);
1032
1033 if (*embedded_id_b == nullptr) {
1034 /* Cannot swap anything if one of the embedded IDs is nullptr. */
1035 return;
1036 }
1037
1038 /* Do not remap internal references to itself here, since embedded IDs pointers also need to be
1039 * potentially remapped in owner ID's data, which will also handle embedded IDs data. */
1040 id_swap(
1041 bmain, *embedded_id_a, *embedded_id_b, do_full_id, false, remapper_id_a, remapper_id_b, 0);
1042 /* Manual 'remap' of owning embedded pointer in owner ID. */
1043 std::swap(*embedded_id_a, *embedded_id_b);
1044
1045 /* Restore internal pointers to the swapped embedded IDs in their owners' data. This also
1046 * includes the potential self-references inside the embedded IDs themselves. */
1047 if (remapper_id_a != nullptr) {
1048 remapper_id_a->add(*embedded_id_b, *embedded_id_a);
1049 }
1050 if (remapper_id_b != nullptr) {
1051 remapper_id_b->add(*embedded_id_a, *embedded_id_b);
1052 }
1053 }
1054}
1055
1057 Main *bmain, ID *id_a, ID *id_b, const bool do_self_remap, const int self_remap_flags)
1058{
1059 id_swap(bmain, id_a, id_b, false, do_self_remap, nullptr, nullptr, self_remap_flags);
1060}
1061
1063 Main *bmain, ID *id_a, ID *id_b, const bool do_self_remap, const int self_remap_flags)
1064{
1065 id_swap(bmain, id_a, id_b, true, do_self_remap, nullptr, nullptr, self_remap_flags);
1066}
1067
1069{
1070 ID *newid = nullptr;
1071
1072 if (id && (ID_REAL_USERS(id) > 1)) {
1073 /* If property isn't editable,
1074 * we're going to have an extra block hanging around until we save. */
1075 if (RNA_property_editable(ptr, prop)) {
1076 Main *bmain = CTX_data_main(C);
1077 /* copy animation actions too */
1078 newid = BKE_id_copy_ex(bmain, id, nullptr, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ACTIONS);
1079 if (newid != nullptr) {
1080 /* us is 1 by convention with new IDs, but RNA_property_pointer_set
1081 * will also increment it, decrement it here. */
1082 id_us_min(newid);
1083
1084 /* assign copy */
1085 PointerRNA idptr = RNA_id_pointer_create(newid);
1086 RNA_property_pointer_set(ptr, prop, idptr, nullptr);
1087 RNA_property_update(C, ptr, prop);
1088
1089 return true;
1090 }
1091 }
1092 }
1093
1094 return false;
1095}
1096
1098{
1099 ID **id_pointer = cb_data->id_pointer;
1100 const LibraryForeachIDCallbackFlag cb_flag = cb_data->cb_flag;
1101 if (cb_flag & IDWALK_CB_USER) {
1102 id_us_plus(*id_pointer);
1103 }
1104 if (cb_flag & IDWALK_CB_USER_ONE) {
1105 id_us_ensure_real(*id_pointer);
1106 }
1107
1108 return IDWALK_RET_NOP;
1109}
1110
1112{
1113 ID **id_pointer = cb_data->id_pointer;
1114 const LibraryForeachIDCallbackFlag cb_flag = cb_data->cb_flag;
1115 if (cb_flag & IDWALK_CB_USER) {
1116 id_us_min(*id_pointer);
1117 }
1118 /* We can do nothing in IDWALK_CB_USER_ONE case! */
1119
1120 return IDWALK_RET_NOP;
1121}
1122
1124{
1125 ID *id = static_cast<ID *>(idv);
1126
1127 BLI_assert(bmain != nullptr);
1128 if ((id->tag & ID_TAG_NO_MAIN) == 0) {
1129 return;
1130 }
1131
1132 if ((id->tag & ID_TAG_NOT_ALLOCATED) != 0) {
1133 /* We cannot add non-allocated ID to Main! */
1134 return;
1135 }
1136
1137 /* We cannot allow non-userrefcounting IDs in Main database! */
1138 if ((id->tag & ID_TAG_NO_USER_REFCOUNT) != 0) {
1140 }
1141
1142 ListBase *lb = which_libbase(bmain, GS(id->name));
1143 BKE_main_lock(bmain);
1144 BLI_addtail(lb, id);
1145 /* We need to allow adding extra datablocks into libraries too, e.g. to support generating new
1146 * overrides for recursive resync. */
1147 BKE_id_new_name_validate(*bmain, *lb, *id, nullptr, IDNewNameMode::RenameExistingNever, true);
1148 /* alphabetic insertion: is in new_id */
1150 bmain->is_memfile_undo_written = false;
1151 BKE_main_unlock(bmain);
1152
1154}
1155
1157{
1158 ID *id = static_cast<ID *>(idv);
1159
1160 BLI_assert(bmain != nullptr);
1161 if ((id->tag & ID_TAG_NO_MAIN) != 0) {
1162 return;
1163 }
1164
1165 /* For now, allow userrefcounting IDs to get out of Main - can be handy in some cases... */
1166
1167 ListBase *lb = which_libbase(bmain, GS(id->name));
1168 BKE_main_lock(bmain);
1169 BLI_remlink(lb, id);
1170 BKE_main_namemap_remove_id(*bmain, *id);
1171 id->tag |= ID_TAG_NO_MAIN;
1172 bmain->is_memfile_undo_written = false;
1173 BKE_main_unlock(bmain);
1174}
1175
1177{
1178 ID *id = static_cast<ID *>(idv);
1179
1180 if ((id->tag & ID_TAG_NO_USER_REFCOUNT) == 0) {
1181 return;
1182 }
1183
1185 id->tag &= ~ID_TAG_NO_USER_REFCOUNT;
1186}
1187
1189{
1190 ID *id = static_cast<ID *>(idv);
1191
1192 /* We do not allow IDs in Main database to not be userrefcounting. */
1193 if ((id->tag & ID_TAG_NO_USER_REFCOUNT) != 0 || (id->tag & ID_TAG_NO_MAIN) != 0) {
1194 return;
1195 }
1196
1198 id->tag |= ID_TAG_NO_USER_REFCOUNT;
1199}
1200
1201void BKE_main_id_tag_listbase(ListBase *lb, const int tag, const bool value)
1202{
1203 ID *id;
1204 if (value) {
1205 for (id = static_cast<ID *>(lb->first); id; id = static_cast<ID *>(id->next)) {
1206 id->tag |= tag;
1207 }
1208 }
1209 else {
1210 const int ntag = ~tag;
1211 for (id = static_cast<ID *>(lb->first); id; id = static_cast<ID *>(id->next)) {
1212 id->tag &= ntag;
1213 }
1214 }
1215}
1216
1217void BKE_main_id_tag_idcode(Main *mainvar, const short type, const int tag, const bool value)
1218{
1219 ListBase *lb = which_libbase(mainvar, type);
1220
1221 BKE_main_id_tag_listbase(lb, tag, value);
1222}
1223
1224void BKE_main_id_tag_all(Main *mainvar, const int tag, const bool value)
1225{
1226 MainListsArray lbarray = BKE_main_lists_get(*mainvar);
1227 int a = lbarray.size();
1228 while (a--) {
1229 BKE_main_id_tag_listbase(lbarray[a], tag, value);
1230 }
1231}
1232
1233void BKE_main_id_flag_listbase(ListBase *lb, const int flag, const bool value)
1234{
1235 ID *id;
1236 if (value) {
1237 for (id = static_cast<ID *>(lb->first); id; id = static_cast<ID *>(id->next)) {
1238 id->tag |= flag;
1239 }
1240 }
1241 else {
1242 const int nflag = ~flag;
1243 for (id = static_cast<ID *>(lb->first); id; id = static_cast<ID *>(id->next)) {
1244 id->tag &= nflag;
1245 }
1246 }
1247}
1248
1249void BKE_main_id_flag_all(Main *bmain, const int flag, const bool value)
1250{
1251 MainListsArray lbarray = BKE_main_lists_get(*bmain);
1252 int a = lbarray.size();
1253 while (a--) {
1254 BKE_main_id_flag_listbase(lbarray[a], flag, value);
1255 }
1256}
1257
1259{
1260 int lb_len = 0;
1261 LISTBASE_FOREACH (ID *, id, lb) {
1262 if (!ID_IS_LINKED(id)) {
1263 lb_len += 1;
1264 }
1265 }
1266 if (lb_len <= 1) {
1267 return;
1268 }
1269
1270 /* Fill an array because renaming sorts. */
1271 ID **id_array = MEM_malloc_arrayN<ID *>(size_t(lb_len), __func__);
1272 GSet *gset = BLI_gset_str_new_ex(__func__, lb_len);
1273 int i = 0;
1274 LISTBASE_FOREACH (ID *, id, lb) {
1275 if (!ID_IS_LINKED(id)) {
1276 id_array[i] = id;
1277 i++;
1278 }
1279 }
1280 for (i = 0; i < lb_len; i++) {
1281 if (!BLI_gset_add(gset, BKE_id_name(*id_array[i]))) {
1283 *bmain, *lb, *id_array[i], nullptr, IDNewNameMode::RenameExistingNever, false);
1284 }
1285 }
1286 BLI_gset_free(gset, nullptr);
1287 MEM_freeN(id_array);
1288}
1289
1291{
1292 Object *ob;
1293
1294 /* flag for full recalc */
1295 for (ob = static_cast<Object *>(bmain->objects.first); ob;
1296 ob = static_cast<Object *>(ob->id.next))
1297 {
1298 if (ID_IS_LINKED(ob)) {
1300 }
1301 }
1302
1303 DEG_id_type_tag(bmain, ID_OB);
1304}
1305
1306/* *********** ALLOC AND FREE *****************
1307 *
1308 * BKE_libblock_free(ListBase *lb, ID *id )
1309 * provide a list-basis and data-block, but only ID is read
1310 *
1311 * void *BKE_libblock_alloc(ListBase *lb, type, name)
1312 * inserts in list and returns a new ID
1313 *
1314 * **************************** */
1315
1317{
1318 if (!id.runtime) {
1319 id.runtime = MEM_new<blender::bke::id::ID_Runtime>(__func__);
1320 }
1321}
1322
1323size_t BKE_libblock_get_alloc_info(short type, const char **r_name)
1324{
1325 const IDTypeInfo *id_type = BKE_idtype_get_info_from_idcode(type);
1326
1327 if (id_type == nullptr) {
1328 if (r_name != nullptr) {
1329 *r_name = nullptr;
1330 }
1331 return 0;
1332 }
1333
1334 if (r_name != nullptr) {
1335 *r_name = id_type->name;
1336 }
1337 return id_type->struct_size;
1338}
1339
1341{
1342 const char *name;
1343 size_t size = BKE_libblock_get_alloc_info(type, &name);
1344 if (size != 0) {
1345 ID *id = static_cast<ID *>(MEM_callocN(size, name));
1346 return id;
1347 }
1348 BLI_assert_msg(0, "Request to allocate unknown data type");
1349 return nullptr;
1350}
1351
1353 std::optional<Library *> owner_library,
1354 short type,
1355 const char *name,
1356 const int flag)
1357{
1359 BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) != 0 || bmain != nullptr);
1361
1362 ID *id = BKE_libblock_alloc_notest(type);
1364
1365 if (id) {
1366 if ((flag & LIB_ID_CREATE_NO_MAIN) != 0) {
1367 id->tag |= ID_TAG_NO_MAIN;
1368 }
1369 if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) != 0) {
1370 id->tag |= ID_TAG_NO_USER_REFCOUNT;
1371 }
1372 if (flag & LIB_ID_CREATE_LOCAL) {
1373 id->tag |= ID_TAG_LOCALIZED;
1374 }
1375
1376 id->icon_id = 0;
1377 *((short *)id->name) = type;
1378 if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
1379 id->us = 1;
1380 }
1381 if ((flag & LIB_ID_CREATE_NO_MAIN) == 0) {
1382 /* Note that 2.8x versioning has tested not to cause conflicts. Node trees are
1383 * skipped in this check to allow adding a geometry node tree for versioning. */
1384 BLI_assert(bmain->is_locked_for_linking == false || ELEM(type, ID_WS, ID_GR, ID_NT));
1385 ListBase *lb = which_libbase(bmain, type);
1386
1387 /* This is important in "read-file do-version after lib-link" context mainly, but is a good
1388 * behavior for consistency in general: ID created for a Main should get that main's current
1389 * library pointer.
1390 *
1391 * NOTE: A bit convoluted.
1392 * - When Main has a defined `curlib`, it is assumed to be a split main containing only IDs
1393 * from that library. In that case, the library can be set later, and it avoids
1394 * synchronization issues in the namemap between the one of that temp 'library' Main and
1395 * the library ID runtime namemap itself. In a way, the ID can be assumed local to the
1396 * current Main, for its assignment to this Main.
1397 * - In all other cases, the Main is assumed 'complete', i.e. containing all local and
1398 * linked IDs, In that case, it is critical that the ID gets the correct library assigned
1399 * now, to ensure that the call to #BKE_id_new_name_validate gives a fully valid result
1400 * once it has been assigned to the current Main.
1401 */
1402 if (bmain->curlib) {
1403 id->lib = nullptr;
1404 }
1405 else {
1406 id->lib = owner_library ? *owner_library : nullptr;
1407 }
1408
1409 BKE_main_lock(bmain);
1410 BLI_addtail(lb, id);
1412 bmain->is_memfile_undo_written = false;
1413 /* alphabetic insertion: is in new_id */
1414 BKE_main_unlock(bmain);
1415
1416 /* Split Main case, now the ID should get the Main's #curlib. */
1417 if (bmain->curlib) {
1418 BLI_assert(!owner_library || *owner_library == bmain->curlib);
1419 id->lib = bmain->curlib;
1420 }
1421
1422 /* This assert avoids having to keep name_map consistency when changing the library of an ID,
1423 * if this check is not true anymore it will have to be done here too. */
1424 BLI_assert(bmain->curlib == nullptr || bmain->curlib->runtime->name_map == nullptr);
1425
1426 /* TODO: to be removed from here! */
1427 if ((flag & LIB_ID_CREATE_NO_DEG_TAG) == 0) {
1428 DEG_id_type_tag(bmain, type);
1429 }
1430 }
1431 else {
1432 BLI_strncpy(id->name + 2, name, sizeof(id->name) - 2);
1433 id->lib = owner_library ? *owner_library : nullptr;
1434 }
1435
1436 /* We also need to ensure a valid `session_uid` for some non-main data (like embedded IDs).
1437 * IDs not allocated however should not need those (this would e.g. avoid generating session
1438 * UIDs for depsgraph evaluated IDs, if it was using this function). */
1439 if ((flag & LIB_ID_CREATE_NO_ALLOCATE) == 0) {
1441 }
1442 }
1443
1444 return id;
1445}
1446
1447void *BKE_libblock_alloc(Main *bmain, short type, const char *name, const int flag)
1448{
1449 return BKE_libblock_alloc_in_lib(bmain, std::nullopt, type, name, flag);
1450}
1451
1453{
1454 const IDTypeInfo *idtype_info = BKE_idtype_get_info_from_id(id);
1455
1456 if (idtype_info != nullptr) {
1457 if (idtype_info->init_data != nullptr) {
1458 idtype_info->init_data(id);
1459 }
1460 return;
1461 }
1462
1463 BLI_assert_msg(0, "IDType Missing IDTypeInfo");
1464}
1465
1467{
1468 id->runtime->remap.status = 0;
1469 id->runtime->remap.skipped_refcounted = 0;
1470 id->runtime->remap.skipped_direct = 0;
1471 id->runtime->remap.skipped_indirect = 0;
1472}
1473
1474/* ********** ID session-wise UID management. ********** */
1476
1478{
1479 if (id->session_uid == MAIN_ID_SESSION_UID_UNSET) {
1480 BLI_assert((id->tag & ID_TAG_TEMP_MAIN) == 0); /* Caller must ensure this. */
1481 id->session_uid = atomic_add_and_fetch_uint32(&global_session_uid, 1);
1482 /* In case overflow happens, still assign a valid ID. This way opening files many times works
1483 * correctly. */
1484 if (UNLIKELY(id->session_uid == MAIN_ID_SESSION_UID_UNSET)) {
1485 id->session_uid = atomic_add_and_fetch_uint32(&global_session_uid, 1);
1486 }
1487 }
1488}
1489
1495
1497 std::optional<Library *> owner_library,
1498 const short type,
1499 const char *name)
1500
1501{
1502 BLI_assert(bmain != nullptr);
1503
1504 if (name == nullptr) {
1506 }
1507
1508 ID *id = static_cast<ID *>(BKE_libblock_alloc_in_lib(bmain, owner_library, type, name, 0));
1510
1511 return id;
1512}
1513
1514void *BKE_id_new(Main *bmain, const short type, const char *name)
1515{
1516 return BKE_id_new_in_lib(bmain, std::nullopt, type, name);
1517}
1518
1519void *BKE_id_new_nomain(const short type, const char *name)
1520{
1521 if (name == nullptr) {
1523 }
1524
1525 ID *id = static_cast<ID *>(BKE_libblock_alloc(
1526 nullptr,
1527 type,
1528 name,
1531
1532 return id;
1533}
1534
1536 std::optional<Library *> owner_library,
1537 const ID *id,
1538 std::optional<const ID *> new_owner_id,
1539 ID **new_id_p,
1540 const int orig_flag)
1541{
1542 ID *new_id = *new_id_p;
1543 int flag = orig_flag;
1544
1545 const bool is_embedded_id = (id->flag & ID_FLAG_EMBEDDED_DATA) != 0;
1546
1547 BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) != 0 || bmain != nullptr);
1550
1551 /* Embedded ID handling.
1552 *
1553 * NOTE: This makes copying code of embedded IDs non-reentrant (i.e. copying an embedded ID as
1554 * part of another embedded ID would not work properly). This is not an issue currently, but may
1555 * need to be addressed in the future. */
1556 if ((bmain != nullptr) && is_embedded_id) {
1558 }
1559
1560 /* The id->flag bits to copy over. */
1561 const int copy_idflag_mask = ID_FLAG_EMBEDDED_DATA;
1562 /* The id->tag bits to copy over. */
1563 const int copy_idtag_mask =
1564 /* Only copy potentially existing 'linked' tags if the new ID is being placed into a library.
1565 *
1566 * Further tag and paths remapping is handled in #BKE_id_copy_in_lib.
1567 */
1568 ((owner_library && *owner_library) ? (ID_TAG_EXTERN | ID_TAG_INDIRECT) : 0);
1569
1570 if ((flag & LIB_ID_CREATE_NO_ALLOCATE) != 0) {
1571 /* `new_id_p` already contains pointer to allocated memory.
1572 * Clear and initialize it similar to BKE_libblock_alloc_in_lib. */
1573 const size_t size = BKE_libblock_get_alloc_info(GS(id->name), nullptr);
1574 memset(new_id, 0, size);
1576 STRNCPY(new_id->name, id->name);
1577 new_id->us = 0;
1579 new_id->lib = owner_library ? *owner_library : id->lib;
1580 /* TODO: Is this entirely consistent with BKE_libblock_alloc_in_lib, and can we
1581 * deduplicate the initialization code? */
1582 }
1583 else {
1584 new_id = static_cast<ID *>(
1585 BKE_libblock_alloc_in_lib(bmain, owner_library, GS(id->name), BKE_id_name(*id), flag));
1586 }
1587 BLI_assert(new_id != nullptr);
1588
1590 new_id->tag |= ID_TAG_COPIED_ON_EVAL;
1591 }
1592 else {
1593 new_id->tag &= ~ID_TAG_COPIED_ON_EVAL;
1594 }
1595
1596 const size_t id_len = BKE_libblock_get_alloc_info(GS(new_id->name), nullptr);
1597 const size_t id_offset = sizeof(ID);
1598 if (int(id_len) - int(id_offset) > 0) { /* signed to allow neg result */ /* XXX ????? */
1599 const char *cp = (const char *)id;
1600 char *cpn = (char *)new_id;
1601
1602 memcpy(cpn + id_offset, cp + id_offset, id_len - id_offset);
1603 }
1604
1605 new_id->flag = (new_id->flag & ~copy_idflag_mask) | (id->flag & copy_idflag_mask);
1606 new_id->tag = (new_id->tag & ~copy_idtag_mask) | (id->tag & copy_idtag_mask);
1607
1608 /* Embedded ID data handling. */
1609 if (is_embedded_id && (orig_flag & LIB_ID_CREATE_NO_MAIN) == 0) {
1610 new_id->tag &= ~ID_TAG_NO_MAIN;
1611 }
1612 /* NOTE: This also needs to run for ShapeKeys, which are not (yet) actual embedded IDs.
1613 * NOTE: for now, keep existing owner ID (i.e. owner of the source embedded ID) if no new one
1614 * is given. In some cases (e.g. depsgraph), this is important for later remapping to work
1615 * properly.
1616 */
1617 if (new_owner_id.has_value()) {
1618 const IDTypeInfo *idtype = BKE_idtype_get_info_from_id(new_id);
1619 BLI_assert(idtype->owner_pointer_get != nullptr);
1620 ID **owner_id_pointer = idtype->owner_pointer_get(new_id, false);
1621 if (owner_id_pointer) {
1622 *owner_id_pointer = const_cast<ID *>(*new_owner_id);
1623 if (*new_owner_id == nullptr) {
1624 /* If the new id does not have an owner, it's also not embedded. */
1625 new_id->flag &= ~ID_FLAG_EMBEDDED_DATA;
1626 }
1627 }
1628 }
1629
1630 /* We do not want any handling of user-count in code duplicating the data here, we do that all
1631 * at once in id_copy_libmanagement_cb() at the end. */
1632 const int copy_data_flag = orig_flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
1633
1634 if (id->properties) {
1635 new_id->properties = IDP_CopyProperty_ex(id->properties, copy_data_flag);
1636 }
1637 if (id->system_properties) {
1638 new_id->system_properties = IDP_CopyProperty_ex(id->system_properties, copy_data_flag);
1639 }
1640
1641 /* This is never duplicated, only one existing ID should have a given weak ref to library/ID. */
1642 new_id->library_weak_reference = nullptr;
1643
1644 if ((orig_flag & LIB_ID_COPY_NO_LIB_OVERRIDE) == 0) {
1646 /* We do not want to copy existing override rules here, as they would break the proper
1647 * remapping between IDs. Proper overrides rules will be re-generated anyway. */
1648 BKE_lib_override_library_copy(new_id, id, false);
1649 }
1650 else if (ID_IS_OVERRIDE_LIBRARY_VIRTUAL(id)) {
1651 /* Just ensure virtual overrides do get properly tagged, there is not actual override data to
1652 * copy here. */
1654 }
1655 }
1656
1657 if (id_can_have_animdata(new_id)) {
1658 IdAdtTemplate *iat = (IdAdtTemplate *)new_id;
1659
1660 /* the duplicate should get a copy of the animdata */
1661 if ((flag & LIB_ID_COPY_NO_ANIMDATA) == 0) {
1662 /* Note that even though horrors like root node-trees are not in bmain, the actions they use
1663 * in their anim data *are* in bmain... super-mega-hooray. */
1664 BLI_assert((copy_data_flag & LIB_ID_COPY_ACTIONS) == 0 ||
1665 (copy_data_flag & LIB_ID_CREATE_NO_MAIN) == 0);
1666 iat->adt = BKE_animdata_copy_in_lib(bmain, owner_library, iat->adt, copy_data_flag);
1667 }
1668 else {
1669 iat->adt = nullptr;
1670 }
1671 }
1672
1674 if (id->asset_data) {
1675 new_id->asset_data = BKE_asset_metadata_copy(id->asset_data);
1676 }
1677 }
1678
1679 if ((flag & LIB_ID_CREATE_NO_DEG_TAG) == 0 && (flag & LIB_ID_CREATE_NO_MAIN) == 0) {
1680 DEG_id_type_tag(bmain, GS(new_id->name));
1681 }
1682
1683 if (owner_library && *owner_library && ((*owner_library)->flag & LIBRARY_FLAG_IS_ARCHIVE) != 0) {
1685 }
1686
1688 ID_NEW_SET(id, new_id);
1689 }
1690
1691 *new_id_p = new_id;
1692}
1693
1694void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **new_id_p, const int orig_flag)
1695{
1696 BKE_libblock_copy_in_lib(bmain, std::nullopt, id, std::nullopt, new_id_p, orig_flag);
1697}
1698
1699void *BKE_libblock_copy(Main *bmain, const ID *id)
1700{
1701 ID *idn = nullptr;
1702
1703 BKE_libblock_copy_in_lib(bmain, std::nullopt, id, std::nullopt, &idn, 0);
1704
1705 return idn;
1706}
1707
1708/* ***************** ID ************************ */
1709
1711 const short type,
1712 const char *name,
1713 const std::optional<Library *> lib)
1714{
1715 const ListBase *lb = which_libbase(bmain, type);
1716 BLI_assert(lb != nullptr);
1717
1718 ID *id = static_cast<ID *>(BLI_findstring(lb, name, offsetof(ID, name) + 2));
1719 if (lib) {
1720 while (id && id->lib != *lib) {
1721 id = static_cast<ID *>(BLI_listbase_findafter_string(
1722 reinterpret_cast<Link *>(id), name, offsetof(ID, name) + 2));
1723 }
1724 }
1725 return id;
1726}
1727
1728ID *BKE_libblock_find_session_uid(Main *bmain, const short type, const uint32_t session_uid)
1729{
1730 const ListBase *lb = which_libbase(bmain, type);
1731 BLI_assert(lb != nullptr);
1732 LISTBASE_FOREACH (ID *, id, lb) {
1733 if (id->session_uid == session_uid) {
1734 return id;
1735 }
1736 }
1737 return nullptr;
1738}
1739
1740ID *BKE_libblock_find_session_uid(Main *bmain, const uint32_t session_uid)
1741{
1742 ID *id_iter;
1743 FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
1744 if (id_iter->session_uid == session_uid) {
1745 return id_iter;
1746 }
1747 }
1749 return nullptr;
1750}
1751
1753 const short type,
1754 const char *name,
1755 const char *lib_name)
1756{
1757 const bool is_linked = (lib_name && lib_name[0] != '\0');
1758 Library *library = is_linked ? reinterpret_cast<Library *>(
1759 BKE_libblock_find_name(bmain, ID_LI, lib_name, nullptr)) :
1760 nullptr;
1761 if (is_linked && !library) {
1762 return nullptr;
1763 }
1764 return BKE_libblock_find_name(bmain, type, name, library);
1765}
1766
1768 short type,
1769 const char *name,
1770 const char *lib_filepath_abs)
1771{
1772 const bool is_linked = (lib_filepath_abs && lib_filepath_abs[0] != '\0');
1773 Library *library = nullptr;
1774 if (is_linked) {
1775 const ListBase *lb = which_libbase(bmain, ID_LI);
1776 LISTBASE_FOREACH (ID *, id_iter, lb) {
1777 Library *lib_iter = reinterpret_cast<Library *>(id_iter);
1778 if (STREQ(lib_iter->runtime->filepath_abs, lib_filepath_abs)) {
1779 library = lib_iter;
1780 break;
1781 }
1782 }
1783 if (!library) {
1784 return nullptr;
1785 }
1786 }
1787 return BKE_libblock_find_name(bmain, type, name, library);
1788}
1789
1790void id_sort_by_name(ListBase *lb, ID *id, ID *id_sorting_hint)
1791{
1792#define ID_SORT_STEP_SIZE 512
1793
1794 ID *idtest;
1795
1796 /* insert alphabetically */
1797 if (lb->first == lb->last) {
1798 return;
1799 }
1800
1801 BLI_remlink(lb, id);
1802
1803 /* Check if we can actually insert id before or after id_sorting_hint, if given. */
1804 if (!ELEM(id_sorting_hint, nullptr, id) && id_sorting_hint->lib == id->lib) {
1805 BLI_assert(BLI_findindex(lb, id_sorting_hint) >= 0);
1806
1807 ID *id_sorting_hint_next = static_cast<ID *>(id_sorting_hint->next);
1808 if (BLI_strcasecmp(id_sorting_hint->name, id->name) < 0 &&
1809 (id_sorting_hint_next == nullptr || id_sorting_hint_next->lib != id->lib ||
1810 BLI_strcasecmp(id_sorting_hint_next->name, id->name) > 0))
1811 {
1812 BLI_insertlinkafter(lb, id_sorting_hint, id);
1813 return;
1814 }
1815
1816 ID *id_sorting_hint_prev = static_cast<ID *>(id_sorting_hint->prev);
1817 if (BLI_strcasecmp(id_sorting_hint->name, id->name) > 0 &&
1818 (id_sorting_hint_prev == nullptr || id_sorting_hint_prev->lib != id->lib ||
1819 BLI_strcasecmp(id_sorting_hint_prev->name, id->name) < 0))
1820 {
1821 BLI_insertlinkbefore(lb, id_sorting_hint, id);
1822 return;
1823 }
1824 }
1825
1826 void *item_array[ID_SORT_STEP_SIZE];
1827 int item_array_index;
1828
1829 /* Step one: We go backward over a whole chunk of items at once, until we find a limit item
1830 * that is lower than, or equal (should never happen!) to the one we want to insert. */
1831 /* NOTE: We start from the end, because in typical 'heavy' case (insertion of lots of IDs at
1832 * once using the same base name), newly inserted items will generally be towards the end
1833 * (higher extension numbers). */
1834 bool is_in_library = false;
1835 item_array_index = ID_SORT_STEP_SIZE - 1;
1836 for (idtest = static_cast<ID *>(lb->last); idtest != nullptr;
1837 idtest = static_cast<ID *>(idtest->prev))
1838 {
1839 if (is_in_library) {
1840 if (idtest->lib != id->lib) {
1841 /* We got out of expected library 'range' in the list, so we are done here and can move on
1842 * to the next step. */
1843 break;
1844 }
1845 }
1846 else if (idtest->lib == id->lib) {
1847 /* We are entering the expected library 'range' of IDs in the list. */
1848 is_in_library = true;
1849 }
1850
1851 if (!is_in_library) {
1852 continue;
1853 }
1854
1855 item_array[item_array_index] = idtest;
1856 if (item_array_index == 0) {
1857 if (BLI_strcasecmp(idtest->name, id->name) <= 0) {
1858 break;
1859 }
1860 item_array_index = ID_SORT_STEP_SIZE;
1861 }
1862 item_array_index--;
1863 }
1864
1865 /* Step two: we go forward in the selected chunk of items and check all of them, as we know
1866 * that our target is in there. */
1867
1868 /* If we reached start of the list, current item_array_index is off-by-one.
1869 * Otherwise, we already know that it points to an item lower-or-equal-than the one we want to
1870 * insert, no need to redo the check for that one.
1871 * So we can increment that index in any case. */
1872 for (item_array_index++; item_array_index < ID_SORT_STEP_SIZE; item_array_index++) {
1873 idtest = static_cast<ID *>(item_array[item_array_index]);
1874 if (BLI_strcasecmp(idtest->name, id->name) > 0) {
1875 BLI_insertlinkbefore(lb, idtest, id);
1876 break;
1877 }
1878 }
1879 if (item_array_index == ID_SORT_STEP_SIZE) {
1880 if (idtest == nullptr) {
1881 /* If idtest is nullptr here, it means that in the first loop, the last comparison was
1882 * performed exactly on the first item of the list, and that it also failed. And that the
1883 * second loop was not walked at all.
1884 *
1885 * In other words, if `id` is local, all the items in the list are greater than the inserted
1886 * one, so we can put it at the start of the list. Or, if `id` is linked, it is the first one
1887 * of its library, and we can put it at the very end of the list. */
1888 if (ID_IS_LINKED(id)) {
1889 BLI_addtail(lb, id);
1890 }
1891 else {
1892 BLI_addhead(lb, id);
1893 }
1894 }
1895 else {
1896 BLI_insertlinkafter(lb, idtest, id);
1897 }
1898 }
1899
1900#undef ID_SORT_STEP_SIZE
1901}
1902
1904 ListBase &lb,
1905 ID &id,
1906 const char *newname,
1907 IDNewNameMode mode,
1908 const bool do_linked_data)
1909{
1910 char name[MAX_ID_NAME - 2];
1911
1912 /* If library, don't rename (unless explicitly required), but do ensure proper sorting. */
1913 if (!do_linked_data && ID_IS_LINKED(&id)) {
1914 id_sort_by_name(&lb, &id, nullptr);
1915
1916 return {IDNewNameResult::Action::UNCHANGED, nullptr};
1917 }
1918
1919 /* If no name given, use name of current ID. */
1920 if (newname == nullptr) {
1921 newname = BKE_id_name(id);
1922 }
1923 /* Make a copy of given name (newname args can be const). */
1924 STRNCPY(name, newname);
1925
1926 if (name[0] == '\0') {
1927 /* Disallow empty names. */
1929 }
1930 else {
1931 /* Disallow non UTF8 chars,
1932 * the interface checks for this but new ID's based on file names don't. */
1934 }
1935
1936 /* Store original requested new name, in modes that may solve name conflict by renaming the
1937 * existing conflicting ID. */
1938 char orig_name[MAX_ID_NAME - 2];
1940 STRNCPY(orig_name, name);
1941 }
1942
1943 const bool had_name_collision = BKE_main_namemap_get_unique_name(bmain, id, name);
1944
1945 if (had_name_collision &&
1947 {
1948 char prev_name[MAX_ID_NAME - 2];
1949 char prev_name_root[MAX_ID_NAME - 2];
1950 int prev_number = 0;
1951 char new_name_root[MAX_ID_NAME - 2];
1952 int new_number = 0;
1953 STRNCPY(prev_name, BKE_id_name(id));
1955 BLI_string_split_name_number(BKE_id_name(id), '.', prev_name_root, &prev_number);
1956 BLI_string_split_name_number(name, '.', new_name_root, &new_number);
1957 }
1958
1959 ID *id_other = BKE_libblock_find_name(&bmain, GS(id.name), orig_name, id.lib);
1960 BLI_assert(id_other);
1961
1962 /* In case of #RenameExistingSameRoot, the existing ID (`id_other`) is only renamed if it has
1963 * the same 'root' name as the current name of the renamed `id`. */
1965 (mode == IDNewNameMode::RenameExistingSameRoot && STREQ(prev_name_root, new_name_root)))
1966 {
1967 BLI_strncpy(id_other->name + 2, name, sizeof(id_other->name) - 2);
1968 id_sort_by_name(&lb, id_other, nullptr);
1969
1970 const bool is_idname_changed = !STREQ(BKE_id_name(id), orig_name);
1972 if (is_idname_changed) {
1973 BLI_strncpy(id.name + 2, orig_name, sizeof(id.name) - 2);
1975 }
1976 id_sort_by_name(&lb, &id, nullptr);
1977
1978 return result;
1979 }
1980 }
1981
1982 /* The requested new name may be available (not collide with any other existing ID name), but
1983 * still differ from the current name of the renamed ID.
1984 * Conversely, the requested new name may have been colliding with an existing one, and the
1985 * generated unique name may end up being the current ID's name. */
1986 const bool is_idname_changed = !STREQ(BKE_id_name(id), name);
1987
1989 if (is_idname_changed) {
1990 BLI_strncpy(id.name + 2, name, sizeof(id.name) - 2);
1991 result.action = had_name_collision ? IDNewNameResult::Action::RENAMED_COLLISION_ADJUSTED :
1993 }
1994 else if (had_name_collision) {
1996 }
1997 id_sort_by_name(&lb, &id, nullptr);
1998 return result;
1999}
2000
2002{
2003 ID *id;
2004
2005 FOREACH_MAIN_ID_BEGIN (bmain, id) {
2007 }
2009}
2010
2012{
2013 ID **id_pointer = cb_data->id_pointer;
2014 const LibraryForeachIDCallbackFlag cb_flag = cb_data->cb_flag;
2015 const bool do_linked_only = bool(POINTER_AS_INT(cb_data->user_data));
2016
2017 if (*id_pointer == nullptr) {
2018 return IDWALK_RET_NOP;
2019 }
2020 if (do_linked_only && !ID_IS_LINKED(*id_pointer)) {
2021 return IDWALK_RET_NOP;
2022 }
2023
2024 if (cb_flag & IDWALK_CB_USER) {
2025 /* Do not touch to direct/indirect linked status here... */
2026 id_us_plus_no_lib(*id_pointer);
2027 }
2028 if (cb_flag & IDWALK_CB_USER_ONE) {
2029 id_us_ensure_real(*id_pointer);
2030 }
2031
2032 return IDWALK_RET_NOP;
2033}
2034
2035void BKE_main_id_refcount_recompute(Main *bmain, const bool do_linked_only)
2036{
2037 ID *id;
2038
2039 FOREACH_MAIN_ID_BEGIN (bmain, id) {
2040 if (!ID_IS_LINKED(id) && do_linked_only) {
2041 continue;
2042 }
2043 id->us = ID_FAKE_USERS(id);
2044 /* Note that we keep EXTRAUSER tag here, since some UI users may define it too... */
2045 if (id->tag & ID_TAG_EXTRAUSER) {
2046 id->tag &= ~(ID_TAG_EXTRAUSER | ID_TAG_EXTRAUSER_SET);
2048 }
2049 if (ELEM(GS(id->name), ID_SCE, ID_WM, ID_WS)) {
2050 /* These IDs should always have a 'virtual' user. */
2052 }
2053 }
2055
2056 /* Go over whole Main database to re-generate proper user-counts. */
2057 FOREACH_MAIN_ID_BEGIN (bmain, id) {
2059 id,
2061 POINTER_FROM_INT(int(do_linked_only)),
2063 }
2065}
2066
2068 GSet *loop_tags,
2069 MainIDRelations *id_relations,
2070 GSet *done_ids)
2071{
2072 if (BLI_gset_haskey(done_ids, id)) {
2073 return; /* Already checked, nothing else to do. */
2074 }
2075
2076 MainIDRelationsEntry *entry = static_cast<MainIDRelationsEntry *>(
2077 BLI_ghash_lookup(id_relations->relations_from_pointers, id));
2078 BLI_gset_insert(loop_tags, id);
2079 for (MainIDRelationsEntryItem *from_id_entry = entry->from_ids; from_id_entry != nullptr;
2080 from_id_entry = from_id_entry->next)
2081 {
2082 /* Our oh-so-beloved 'from' pointers... Those should always be ignored here, since the actual
2083 * relation we want to check is in the other way around. */
2084 if (from_id_entry->usage_flag & IDWALK_CB_LOOPBACK) {
2085 continue;
2086 }
2087
2088 ID *from_id = from_id_entry->id_pointer.from;
2089
2090 /* Shape-keys are considered 'private' to their owner ID here, and never tagged
2091 * (since they cannot be linked), so we have to switch effective parent to their owner.
2092 */
2093 if (GS(from_id->name) == ID_KE) {
2094 from_id = ((Key *)from_id)->from;
2095 }
2096
2097 if (!ID_IS_LINKED(from_id)) {
2098 /* Local user, early out to avoid some gset querying... */
2099 continue;
2100 }
2101 if (!BLI_gset_haskey(done_ids, from_id)) {
2102 if (BLI_gset_haskey(loop_tags, from_id)) {
2103 /* We are in a 'dependency loop' of IDs, this does not say us anything, skip it.
2104 * Note that this is the situation that can lead to archipelagos of linked data-blocks
2105 * (since all of them have non-local users, they would all be duplicated,
2106 * leading to a loop of unused linked data-blocks that cannot be freed since they all use
2107 * each other...). */
2108 continue;
2109 }
2110 /* Else, recursively check that user ID. */
2111 library_make_local_copying_check(from_id, loop_tags, id_relations, done_ids);
2112 }
2113
2114 if (from_id->tag & ID_TAG_DOIT) {
2115 /* This user will be fully local in future, so far so good,
2116 * nothing to do here but check next user. */
2117 }
2118 else {
2119 /* This user won't be fully local in future, so current ID won't be either.
2120 * And we are done checking it. */
2121 id->tag &= ~ID_TAG_DOIT;
2122 break;
2123 }
2124 }
2125 BLI_gset_add(done_ids, id);
2126 BLI_gset_remove(loop_tags, id, nullptr);
2127}
2128
2130 const Library *lib,
2131 GHash *old_to_new_ids,
2132 const bool untagged_only,
2133 const bool set_fake,
2134 const bool clear_asset_data)
2135{
2136 /* NOTE: Old (2.77) version was simply making (tagging) data-blocks as local,
2137 * without actually making any check whether they were also indirectly used or not...
2138 *
2139 * Current version uses regular id_make_local callback, with advanced pre-processing step to
2140 * detect all cases of IDs currently indirectly used, but which will be used by local data only
2141 * once this function is finished. This allows to avoid any unneeded duplication of IDs, and
2142 * hence all time lost afterwards to remove orphaned linked data-blocks. */
2143
2144 MainListsArray lbarray = BKE_main_lists_get(*bmain);
2145
2146 LinkNode *todo_ids = nullptr;
2147 LinkNode *copied_ids = nullptr;
2148 MemArena *linklist_mem = BLI_memarena_new(512 * sizeof(*todo_ids), __func__);
2149
2150 GSet *done_ids = BLI_gset_ptr_new(__func__);
2151
2152#ifdef DEBUG_TIME
2153 TIMEIT_START(make_local);
2154#endif
2155
2156 BKE_main_relations_create(bmain, 0);
2157
2158#ifdef DEBUG_TIME
2159 printf("Pre-compute current ID relations: Done.\n");
2160 TIMEIT_VALUE_PRINT(make_local);
2161#endif
2162
2163 /* Step 1: Detect data-blocks to make local. */
2164 for (int a = lbarray.size(); a--;) {
2165 ID *id = static_cast<ID *>(lbarray[a]->first);
2166
2167 /* Do not explicitly make local non-linkable IDs (shape-keys, in fact),
2168 * they are assumed to be handled by real data-blocks responsible of them. */
2169 const bool do_skip = (id && !BKE_idtype_idcode_is_linkable(GS(id->name)));
2170
2171 for (; id; id = static_cast<ID *>(id->next)) {
2172 ID *ntree = (ID *)blender::bke::node_tree_from_id(id);
2173
2174 id->tag &= ~ID_TAG_DOIT;
2175 if (ntree != nullptr) {
2176 ntree->tag &= ~ID_TAG_DOIT;
2177 }
2178
2179 if (!ID_IS_LINKED(id)) {
2180 id->tag &= ~(ID_TAG_EXTERN | ID_TAG_INDIRECT | ID_TAG_NEW);
2181 id->flag &= ~ID_FLAG_INDIRECT_WEAK_LINK;
2183 ELEM(lib, nullptr, id->override_library->reference->lib) &&
2184 ((untagged_only == false) || !(id->tag & ID_TAG_PRE_EXISTING)))
2185 {
2186 /* Validating liboverride hierarchy root pointers will happen later in this function,
2187 * rather than doing it for each and every localized ID. */
2189 }
2190 }
2191 /* The check on the fourth line (ID_TAG_PRE_EXISTING) is done so it's possible to tag data
2192 * you don't want to be made local, used for appending data,
2193 * so any libdata already linked won't become local (very nasty
2194 * to discover all your links are lost after appending).
2195 * Also, never ever make proxified objects local, would not make any sense. */
2196 /* Some more notes:
2197 * - Shape-keys are never tagged here (since they are not linkable).
2198 * - Node-trees used in materials etc. have to be tagged manually,
2199 * since they do not exist in Main (!).
2200 * This is ok-ish on 'make local' side of things
2201 * (since those are handled by their 'owner' IDs),
2202 * but complicates slightly the pre-processing of relations between IDs at step 2... */
2203 else if (!do_skip && id->tag & (ID_TAG_EXTERN | ID_TAG_INDIRECT | ID_TAG_NEW) &&
2204 ELEM(lib, nullptr, id->lib) &&
2205 ((untagged_only == false) || !(id->tag & ID_TAG_PRE_EXISTING)))
2206 {
2207 BLI_linklist_prepend_arena(&todo_ids, id, linklist_mem);
2208 id->tag |= ID_TAG_DOIT;
2209
2210 /* Tag those nasty non-ID node-trees,
2211 * but do not add them to todo list, making them local is handled by 'owner' ID.
2212 * This is needed for library_make_local_copying_check() to work OK at step 2. */
2213 if (ntree != nullptr) {
2214 ntree->tag |= ID_TAG_DOIT;
2215 }
2216 }
2217 else {
2218 /* Linked ID that we won't be making local (needed info for step 2, see below). */
2219 BLI_gset_add(done_ids, id);
2220 }
2221 }
2222 }
2223
2224#ifdef DEBUG_TIME
2225 printf("Step 1: Detect data-blocks to make local: Done.\n");
2226 TIMEIT_VALUE_PRINT(make_local);
2227#endif
2228
2229 /* Step 2: Check which data-blocks we can directly make local
2230 * (because they are only used by already, or future, local data),
2231 * others will need to be duplicated. */
2232 GSet *loop_tags = BLI_gset_ptr_new(__func__);
2233 for (LinkNode *it = todo_ids; it; it = it->next) {
2235 static_cast<ID *>(it->link), loop_tags, bmain->relations, done_ids);
2236 BLI_assert(BLI_gset_len(loop_tags) == 0);
2237 }
2238 BLI_gset_free(loop_tags, nullptr);
2239 BLI_gset_free(done_ids, nullptr);
2240
2241 /* Next step will most likely add new IDs, better to get rid of this mapping now. */
2243
2244#ifdef DEBUG_TIME
2245 printf("Step 2: Check which data-blocks we can directly make local: Done.\n");
2246 TIMEIT_VALUE_PRINT(make_local);
2247#endif
2248
2249 const int make_local_flags = clear_asset_data ? LIB_ID_MAKELOCAL_ASSET_DATA_CLEAR : 0;
2250
2251 /* Step 3: Make IDs local, either directly (quick and simple), or using generic process,
2252 * which involves more complex checks and might instead
2253 * create a local copy of original linked ID. */
2254 for (LinkNode *it = todo_ids, *it_next; it; it = it_next) {
2255 it_next = it->next;
2256 ID *id = static_cast<ID *>(it->link);
2257
2258 if (id->tag & ID_TAG_DOIT) {
2259 /* We know all users of this object are local or will be made fully local, even if
2260 * currently there are some indirect usages. So instead of making a copy that we'll likely
2261 * get rid of later, directly make that data block local.
2262 * Saves a tremendous amount of time with complex scenes... */
2263 BKE_lib_id_clear_library_data(bmain, id, make_local_flags);
2264 BKE_lib_id_expand_local(bmain, id, 0);
2265 id->tag &= ~ID_TAG_DOIT;
2266
2267 if (GS(id->name) == ID_OB) {
2269 }
2270 }
2271 else {
2272 /* In this specific case, we do want to make ID local even if it has no local usage yet... */
2273 BKE_lib_id_make_local(bmain, id, make_local_flags | LIB_ID_MAKELOCAL_FULL_LIBRARY);
2274
2275 if (id->newid) {
2276 if (GS(id->newid->name) == ID_OB) {
2278 }
2279
2280 /* Reuse already allocated LinkNode (transferring it from todo_ids to copied_ids). */
2281 BLI_linklist_prepend_nlink(&copied_ids, id, it);
2282 }
2283 }
2284
2285 if (set_fake) {
2286 if (!ELEM(GS(id->name), ID_OB, ID_GR)) {
2287 /* do not set fake user on objects, groups (instancing) */
2288 id_fake_user_set(id);
2289 }
2290 }
2291 }
2292
2293#ifdef DEBUG_TIME
2294 printf("Step 3: Make IDs local: Done.\n");
2295 TIMEIT_VALUE_PRINT(make_local);
2296#endif
2297
2298 /* At this point, we are done with directly made local IDs.
2299 * Now we have to handle duplicated ones, since their
2300 * remaining linked original counterpart may not be needed anymore... */
2301 todo_ids = nullptr;
2302
2303 /* Step 4: We have to remap local usages of old (linked) ID to new (local)
2304 * ID in a separated loop,
2305 * as lbarray ordering is not enough to ensure us we did catch all dependencies
2306 * (e.g. if making local a parent object before its child...). See #48907. */
2307 /* TODO: This is now the biggest step by far (in term of processing time).
2308 * We may be able to gain here by using again main->relations mapping, but...
2309 * this implies BKE_libblock_remap & co to be able to update main->relations on the fly.
2310 * Have to think about it a bit more, and see whether new code is OK first, anyway. */
2311 for (LinkNode *it = copied_ids; it; it = it->next) {
2312 ID *id = static_cast<ID *>(it->link);
2313
2314 BLI_assert(id->newid != nullptr);
2316
2318 if (old_to_new_ids) {
2319 BLI_ghash_insert(old_to_new_ids, id, id->newid);
2320 }
2321
2322 /* Special hack for groups... Thing is, since we can't instantiate them here, we need to
2323 * ensure they remain 'alive' (only instantiation is a real group 'user'... *sigh* See
2324 * #49722. */
2325 if (GS(id->name) == ID_GR && (id->tag & ID_TAG_INDIRECT) != 0) {
2326 id_us_ensure_real(id->newid);
2327 }
2328 }
2329
2330 /* Making some liboverride local may have had some impact on validity of liboverrides hierarchy
2331 * roots, these need to be re-validated/re-generated. */
2333
2334#ifdef DEBUG_TIME
2335 printf("Step 4: Remap local usages of old (linked) ID to new (local) ID: Done.\n");
2336 TIMEIT_VALUE_PRINT(make_local);
2337#endif
2338
2339 /* This is probably more of a hack than something we should do here, but...
2340 * Issue is, the whole copying + remapping done in complex cases above may leave pose-channels
2341 * of armatures in complete invalid state (more precisely, the bone pointers of the
2342 * pose-channels - very crappy cross-data-blocks relationship), so we tag it to be fully
2343 * recomputed, but this does not seems to be enough in some cases, and evaluation code ends up
2344 * trying to evaluate a not-yet-updated armature object's deformations.
2345 * Try "make all local" in 04_01_H.lighting.blend from Agent327 without this, e.g. */
2346 for (Object *ob = static_cast<Object *>(bmain->objects.first); ob;
2347 ob = static_cast<Object *>(ob->id.next))
2348 {
2349 if (ob->data != nullptr && ob->type == OB_ARMATURE && ob->pose != nullptr &&
2350 ob->pose->flag & POSE_RECALC)
2351 {
2352 BKE_pose_rebuild(bmain, ob, static_cast<bArmature *>(ob->data), true);
2353 }
2354 }
2355
2356#ifdef DEBUG_TIME
2357 printf("Hack: Forcefully rebuild armature object poses: Done.\n");
2358 TIMEIT_VALUE_PRINT(make_local);
2359#endif
2360
2362 BLI_memarena_free(linklist_mem);
2363
2364#ifdef DEBUG_TIME
2365 printf("Cleanup and finish: Done.\n");
2366 TIMEIT_END(make_local);
2367#endif
2368}
2369
2371 ID &id,
2373 const IDNewNameMode mode)
2374{
2375 BLI_assert(BKE_id_is_in_main(&bmain, &id));
2376
2377 if (STREQ(BKE_id_name(id), name.c_str())) {
2378 return {IDNewNameResult::Action::UNCHANGED, nullptr};
2379 }
2380 BKE_main_namemap_remove_id(bmain, id);
2381 ListBase &lb = *which_libbase(&bmain, GS(id.name));
2382 IDNewNameResult result = BKE_id_new_name_validate(bmain, lb, id, name.c_str(), mode, true);
2383 if (!ELEM(result.action,
2386 {
2387 bmain.is_memfile_undo_written = false;
2388 }
2389 return result;
2390}
2391
2393 ID &id,
2395 const IDNewNameMode mode)
2396{
2397 const IDNewNameResult result = BKE_libblock_rename(bmain, id, name, mode);
2398
2399 auto deg_tag_id = [](ID &id) -> void {
2401 switch (GS(id.name)) {
2402 case ID_OB: {
2403 Object &ob = reinterpret_cast<Object &>(id);
2404 if (ob.type == OB_MBALL) {
2406 }
2407 break;
2408 }
2409 default:
2410 break;
2411 }
2412 };
2413
2414 switch (result.action) {
2417 break;
2420 deg_tag_id(id);
2421 break;
2423 BLI_assert(result.other_id);
2424 deg_tag_id(*result.other_id);
2425 deg_tag_id(id);
2426 break;
2427 }
2428
2429 return result;
2430}
2431
2432void BKE_id_full_name_get(char name[MAX_ID_FULL_NAME], const ID *id, char separator_char)
2433{
2435
2436 if (ID_IS_LINKED(id)) {
2437 const size_t idname_len = strlen(BKE_id_name(*id));
2438 const size_t libname_len = strlen(BKE_id_name(id->lib->id));
2439
2440 name[idname_len] = separator_char ? separator_char : ' ';
2441 name[idname_len + 1] = '[';
2443 name + idname_len + 2, BKE_id_name(id->lib->id), MAX_ID_FULL_NAME - (idname_len + 2));
2444 name[idname_len + 2 + libname_len] = ']';
2445 name[idname_len + 2 + libname_len + 1] = '\0';
2446 }
2447}
2448
2450 const ID *id,
2451 const bool add_lib_hint,
2452 char separator_char,
2453 int *r_prefix_len)
2454{
2455 int i = 0;
2456
2457 if (add_lib_hint) {
2458 name[i++] = id->lib ? (ID_MISSING(id) ? 'M' : 'L') : ID_IS_OVERRIDE_LIBRARY(id) ? 'O' : ' ';
2459 }
2460 name[i++] = (id->flag & ID_FLAG_FAKEUSER) ? 'F' : ((id->us == 0) ? '0' : ' ');
2461 name[i++] = ' ';
2462
2463 BKE_id_full_name_get(name + i, id, separator_char);
2464
2465 if (r_prefix_len) {
2466 *r_prefix_len = i;
2467 }
2468}
2469
2471{
2472 if (!ID_IS_LINKED(id)) {
2473 return BLI_strdup(id->name);
2474 }
2475
2476 /* Prefix with an ASCII character in the range of 32..96 (visible)
2477 * this ensures we can't have a library ID pair that collide.
2478 * Where 'LIfooOBbarOBbaz' could be ('LIfoo, OBbarOBbaz') or ('LIfooOBbar', 'OBbaz'). */
2479 const char ascii_len = strlen(BKE_id_name(id->lib->id)) + 32;
2480 return BLI_sprintfN("%c%s%s", ascii_len, id->lib->id.name, id->name);
2481}
2482
2483void BKE_id_tag_set_atomic(ID *id, int tag)
2484{
2485 atomic_fetch_and_or_int32(&id->tag, tag);
2486}
2487
2488void BKE_id_tag_clear_atomic(ID *id, int tag)
2489{
2490 atomic_fetch_and_and_int32(&id->tag, ~tag);
2491}
2492
2493bool BKE_id_is_in_main(Main *bmain, ID *id)
2494{
2495 /* We do not want to fail when id is nullptr here, even though this is a bit strange behavior...
2496 */
2497 return (id == nullptr || BLI_findindex(which_libbase(bmain, GS(id->name)), id) != -1);
2498}
2499
2501{
2502 return BKE_id_is_in_main(G_MAIN, id);
2503}
2504
2506{
2507 return ID_IS_EDITABLE(id) && !ID_IS_OVERRIDE_LIBRARY(id) &&
2509}
2510
2511ID *BKE_id_owner_get(ID *id, const bool debug_relationship_assert)
2512{
2513 const IDTypeInfo *idtype = BKE_idtype_get_info_from_id(id);
2514 if (idtype->owner_pointer_get != nullptr) {
2515 ID **owner_id_pointer = idtype->owner_pointer_get(id, debug_relationship_assert);
2516 if (owner_id_pointer != nullptr) {
2517 return *owner_id_pointer;
2518 }
2519 }
2520 return nullptr;
2521}
2522
2523bool BKE_id_is_editable(const Main *bmain, const ID *id)
2524{
2526}
2527
2528bool BKE_id_can_use_id(const ID &id_from, const ID &id_to)
2529{
2530 /* Can't point from linked to local. */
2531 if (id_from.lib && !id_to.lib) {
2532 return false;
2533 }
2534 /* Can't point from ID in main database to one outside of it. */
2535 if (!(id_from.tag & ID_TAG_NO_MAIN) && (id_to.tag & ID_TAG_NO_MAIN)) {
2536 return false;
2537 }
2538
2539 return true;
2540}
2541
2542/************************* Datablock order in UI **************************/
2543
2544static int *id_order_get(ID *id)
2545{
2546 /* Only for workspace tabs currently. */
2547 switch (GS(id->name)) {
2548 case ID_WS:
2549 return &((WorkSpace *)id)->order;
2550 default:
2551 return nullptr;
2552 }
2553}
2554
2555static bool id_order_compare(ID *a, ID *b)
2556{
2557 int *order_a = id_order_get(a);
2558 int *order_b = id_order_get(b);
2559
2560 /* In practice either both or neither are set,
2561 * failing to do this would result in a logically invalid sort function, see #137712. */
2562 BLI_assert((order_a && order_b) || (!order_a && !order_b));
2563
2564 if (order_a && order_b) {
2565 if (*order_a < *order_b) {
2566 return true;
2567 }
2568 if (*order_a > *order_b) {
2569 return false;
2570 }
2571 }
2572
2573 return strcmp(a->name, b->name) < 0;
2574}
2575
2577{
2578 Vector<ID *> ordered;
2579
2580 LISTBASE_FOREACH (ID *, id, lb) {
2581 ordered.append(id);
2582 }
2583
2584 std::sort(ordered.begin(), ordered.end(), id_order_compare);
2585
2586 for (const int i : ordered.index_range()) {
2587 if (int *order = id_order_get(ordered[i])) {
2588 *order = i;
2589 }
2590 }
2591
2592 return ordered;
2593}
2594
2595void BKE_id_reorder(const ListBase *lb, ID *id, ID *relative, bool after)
2596{
2597 int *id_order = id_order_get(id);
2598 int relative_order;
2599
2600 if (relative) {
2601 relative_order = *id_order_get(relative);
2602 }
2603 else {
2604 relative_order = (after) ? BLI_listbase_count(lb) : 0;
2605 }
2606
2607 if (after) {
2608 /* Insert after. */
2609 LISTBASE_FOREACH (ID *, other, lb) {
2610 int *order = id_order_get(other);
2611 if (*order > relative_order) {
2612 (*order)++;
2613 }
2614 }
2615
2616 *id_order = relative_order + 1;
2617 }
2618 else {
2619 /* Insert before. */
2620 LISTBASE_FOREACH (ID *, other, lb) {
2621 int *order = id_order_get(other);
2622 if (*order < relative_order) {
2623 (*order)--;
2624 }
2625 }
2626
2627 *id_order = relative_order - 1;
2628 }
2629}
2630
2632{
2633 if (id->asset_data) {
2634 BKE_asset_metadata_write(writer, id->asset_data);
2635 }
2636
2637 if (id->library_weak_reference != nullptr) {
2638 BLO_write_struct(writer, LibraryWeakReference, id->library_weak_reference);
2639 }
2640
2641 /* ID_WM's id->properties are considered runtime only, and never written in .blend file. */
2642 if (id->properties && !ELEM(GS(id->name), ID_WM)) {
2643 IDP_BlendWrite(writer, id->properties);
2644 }
2645 /* ID_WM's id->system_properties are considered runtime only, and never written in .blend file.
2646 */
2647 if (id->system_properties && !ELEM(GS(id->name), ID_WM)) {
2648 IDP_BlendWrite(writer, id->system_properties);
2649 }
2650
2651 BKE_animdata_blend_write(writer, id);
2652
2653 if (id->override_library) {
2654 BLO_write_struct(writer, IDOverrideLibrary, id->override_library);
2655
2656 BLO_write_struct_list(writer, IDOverrideLibraryProperty, &id->override_library->properties);
2657 LISTBASE_FOREACH (IDOverrideLibraryProperty *, op, &id->override_library->properties) {
2658 BLO_write_string(writer, op->rna_path);
2659
2661 LISTBASE_FOREACH (IDOverrideLibraryPropertyOperation *, opop, &op->operations) {
2662 if (opop->subitem_reference_name) {
2663 BLO_write_string(writer, opop->subitem_reference_name);
2664 }
2665 if (opop->subitem_local_name) {
2666 BLO_write_string(writer, opop->subitem_local_name);
2667 }
2668 }
2669 }
2670 }
2671}
2672
2674 int id;
2675};
2676
2677static_assert(blender::dna::is_ID_v<ID>);
2678static_assert(blender::dna::is_ID_v<Object>);
2679static_assert(!blender::dna::is_ID_v<int>);
2680static_assert(!blender::dna::is_ID_v<ID *>);
2681static_assert(!blender::dna::is_ID_v<const ID>);
2682static_assert(!blender::dna::is_ID_v<ListBase>);
2683static_assert(!blender::dna::is_ID_v<SomeTypeWithIDMember>);
AnimData * BKE_animdata_copy_in_lib(Main *bmain, std::optional< Library * > owner_library, AnimData *adt, int flag)
Definition anim_data.cc:281
void BKE_animdata_blend_write(BlendWriter *writer, ID *id)
bool id_can_have_animdata(const ID *id)
Definition anim_data.cc:73
void BKE_animdata_duplicate_id_action(Main *bmain, ID *id, uint duplicate_flags)
Definition anim_data.cc:438
void BKE_pose_rebuild(Main *bmain, Object *ob, bArmature *arm, bool do_id_user)
AssetMetaData * BKE_asset_metadata_copy(const AssetMetaData *source)
Definition asset.cc:44
void BKE_asset_metadata_free(AssetMetaData **asset_data)
Definition asset.cc:38
void BKE_asset_metadata_write(BlendWriter *writer, AssetMetaData *asset_data)
Definition asset.cc:197
void BKE_bpath_foreach_path_id(BPathForeachPathData *bpath_data, ID *id)
Definition bpath.cc:75
@ BKE_BPATH_FOREACH_PATH_SKIP_MULTIFILE
Definition BKE_bpath.hh:69
Main * CTX_data_main(const bContext *C)
#define G_MAIN
IDProperty * IDP_CopyProperty_ex(const IDProperty *prop, int flag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:845
void IDP_BlendWrite(BlendWriter *writer, const IDProperty *prop)
Definition idprop.cc:1461
const IDTypeInfo * BKE_idtype_get_info_from_id(const ID *id)
Definition idtype.cc:146
@ IDTYPE_FLAGS_NO_ANIMDATA
Definition BKE_idtype.hh:49
@ IDTYPE_FLAGS_NO_COPY
Definition BKE_idtype.hh:33
@ IDTYPE_FLAGS_NO_LIBLINKING
Definition BKE_idtype.hh:35
const IDTypeInfo * BKE_idtype_get_info_from_idcode(short id_code)
Definition idtype.cc:141
const char * BKE_idtype_idcode_to_name(short idcode)
Definition idtype.cc:164
bool BKE_idtype_idcode_is_linkable(short idcode)
Definition idtype.cc:197
IDTypeInfo IDType_ID_LINK_PLACEHOLDER
Definition lib_id.cc:88
Key ** BKE_key_from_id_p(ID *id)
Definition key.cc:1746
Key * BKE_key_from_id(ID *id)
Definition key.cc:1771
@ LIB_ID_MAKELOCAL_INDIRECT
@ LIB_ID_MAKELOCAL_FORCE_LOCAL
@ LIB_ID_MAKELOCAL_LIBOVERRIDE_CLEAR
@ LIB_ID_MAKELOCAL_ASSET_DATA_CLEAR
@ LIB_ID_MAKELOCAL_FULL_LIBRARY
@ LIB_ID_MAKELOCAL_FORCE_COPY
IDNewNameMode
#define MAIN_ID_SESSION_UID_UNSET
#define MAX_ID_FULL_NAME_UI
@ LIB_ID_CREATE_NO_ALLOCATE
@ LIB_ID_COPY_ASSET_METADATA
@ LIB_ID_COPY_ID_NEW_SET
@ LIB_ID_COPY_NO_LIB_OVERRIDE
@ LIB_ID_COPY_SET_COPIED_ON_WRITE
@ LIB_ID_CREATE_LOCAL
@ LIB_ID_COPY_ACTIONS
@ LIB_ID_CREATE_NO_USER_REFCOUNT
@ LIB_ID_COPY_NO_ANIMDATA
@ LIB_ID_CREATE_NO_MAIN
@ LIB_ID_COPY_DEFAULT
@ LIB_ID_CREATE_NO_DEG_TAG
const char * BKE_id_name(const ID &id)
#define MAX_ID_FULL_NAME
void BKE_lib_override_library_main_hierarchy_root_ensure(Main *bmain)
bool BKE_lib_override_library_is_system_defined(const Main *bmain, const ID *id)
void BKE_lib_override_library_copy(ID *dst_id, const ID *src_id, bool do_full_copy)
void BKE_lib_override_library_make_local(Main *bmain, ID *id)
void BKE_library_ID_test_usages(Main *bmain, void *idv, bool *r_is_used_local, bool *r_is_used_linked)
Definition lib_query.cc:633
@ IDWALK_RET_STOP_ITER
@ IDWALK_RET_NOP
LibraryForeachIDCallbackFlag
@ IDWALK_CB_LOOPBACK
@ IDWALK_CB_USER_ONE
@ IDWALK_CB_USER
@ IDWALK_CB_EMBEDDED_NOT_OWNING
@ IDWALK_CB_EMBEDDED
void BKE_library_foreach_ID_link(Main *bmain, ID *id, blender::FunctionRef< LibraryIDLinkCallback > callback, void *user_data, LibraryForeachIDFlag flag)
Definition lib_query.cc:431
@ IDWALK_INCLUDE_UI
@ IDWALK_IGNORE_MISSING_OWNER_ID
@ IDWALK_NOP
@ IDWALK_READONLY
void BKE_libblock_relink_multiple(Main *bmain, const blender::Span< ID * > ids, eIDRemapType remap_type, blender::bke::id::IDRemapper &id_remapper, int remap_flags)
Definition lib_remap.cc:792
@ ID_REMAP_TYPE_REMAP
void void BKE_libblock_remap(Main *bmain, void *old_idv, void *new_idv, int remap_flags) ATTR_NONNULL(1
@ ID_REMAP_SKIP_INDIRECT_USAGE
#define FOREACH_MAIN_ID_END
Definition BKE_main.hh:583
MainListsArray BKE_main_lists_get(Main &bmain)
Definition main.cc:987
ListBase * which_libbase(Main *bmain, short type)
Definition main.cc:902
std::array< ListBase *, INDEX_ID_MAX - 1 > MainListsArray
Definition BKE_main.hh:645
void BKE_main_lock(Main *bmain)
Definition main.cc:486
void BKE_main_relations_create(Main *bmain, short flag)
Definition main.cc:551
#define FOREACH_MAIN_ID_BEGIN(_bmain, _id)
Definition BKE_main.hh:577
const char * BKE_main_blendfile_path(const Main *bmain) ATTR_NONNULL()
Definition main.cc:887
void BKE_main_unlock(Main *bmain)
Definition main.cc:491
void BKE_main_relations_free(Main *bmain)
Definition main.cc:588
void BKE_main_namemap_remove_id(Main &bmain, ID &id)
bool BKE_main_namemap_get_unique_name(Main &bmain, ID &id, char *r_name)
API for Blender-side Rigid Body stuff.
void BKE_rigidbody_ensure_local_object(struct Main *bmain, struct Object *ob)
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
struct GSet GSet
Definition BLI_ghash.h:337
GSet * BLI_gset_ptr_new(const char *info)
bool BLI_gset_haskey(const GSet *gs, const void *key) ATTR_WARN_UNUSED_RESULT
unsigned int BLI_gset_len(const GSet *gs) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:954
void BLI_gset_insert(GSet *gs, void *key)
Definition BLI_ghash.cc:959
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:731
GSet * BLI_gset_str_new_ex(const char *info, unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition BLI_ghash.cc:707
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
bool BLI_gset_add(GSet *gs, void *key)
Definition BLI_ghash.cc:966
bool BLI_gset_remove(GSet *gs, const void *key, GSetKeyFreeFP keyfreefp)
Definition BLI_ghash.cc:999
int BLI_findindex(const ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:586
#define LISTBASE_FOREACH(type, var, list)
void * BLI_findstring(const ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:608
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
void BLI_insertlinkafter(ListBase *listbase, void *vprevlink, void *vnewlink) ATTR_NONNULL(1)
Definition listbase.cc:332
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:131
void BLI_addhead(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:91
int BLI_listbase_count(const ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:524
void * BLI_listbase_findafter_string(Link *link, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:638
void BLI_insertlinkbefore(ListBase *listbase, void *vnextlink, void *vnewlink) ATTR_NONNULL(1)
Definition listbase.cc:371
MemArena * BLI_memarena_new(size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(2) ATTR_MALLOC
void BLI_memarena_free(MemArena *ma) ATTR_NONNULL(1)
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1
#define FILE_MAXFILE
#define FILE_MAX
int BLI_path_normalize(char *path) ATTR_NONNULL(1)
bool BLI_path_is_rel(const char *path) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
bool void BLI_path_rel(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1)
#define FILE_MAXDIR
char * BLI_sprintfN(const char *__restrict format,...) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_PRINTF_FORMAT(1
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
Definition string.cc:41
int char char int BLI_strcasecmp(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:693
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
int BLI_str_utf8_invalid_strip(char *str, size_t str_len) ATTR_NONNULL(1)
#define STRNCPY_UTF8(dst, src)
size_t BLI_string_split_name_number(const char *name, char delim, char *r_name_left, int *r_number) ATTR_NONNULL(1
unsigned int uint
Utility defines for timing/benchmarks.
#define TIMEIT_START(var)
#define TIMEIT_VALUE_PRINT(var)
#define TIMEIT_END(var)
#define POINTER_FROM_INT(i)
#define POINTER_AS_INT(i)
#define UNLIKELY(x)
#define ELEM(...)
#define STREQ(a, b)
#define BLO_write_struct(writer, struct_name, data_ptr)
void BLO_write_string(BlendWriter *writer, const char *data_ptr)
#define BLO_write_struct_list(writer, struct_name, list_ptr)
#define BLT_I18NCONTEXT_ID_ID
#define DATA_(msgid)
#define CLOG_ERROR(clg_ref,...)
Definition CLG_log.h:188
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_id_type_tag(Main *bmain, short id_type)
void DEG_relations_tag_update(Main *bmain)
bool DEG_is_evaluated(const T *id)
T * DEG_get_original(T *id)
ID and Library types, which are fundamental for SDNA.
#define ID_IS_OVERRIDE_LIBRARY_VIRTUAL(_id)
Definition DNA_ID.h:727
@ ID_TAG_NEW
Definition DNA_ID.h:919
@ ID_TAG_COPIED_ON_EVAL
Definition DNA_ID.h:997
@ ID_TAG_EXTRAUSER
Definition DNA_ID.h:878
@ ID_TAG_NO_USER_REFCOUNT
Definition DNA_ID.h:1018
@ ID_TAG_TEMP_MAIN
Definition DNA_ID.h:971
@ ID_TAG_INDIRECT
Definition DNA_ID.h:848
@ ID_TAG_PRE_EXISTING
Definition DNA_ID.h:926
@ ID_TAG_EXTERN
Definition DNA_ID.h:842
@ ID_TAG_LOCALIZED
Definition DNA_ID.h:987
@ ID_TAG_DOIT
Definition DNA_ID.h:1036
@ ID_TAG_NOT_ALLOCATED
Definition DNA_ID.h:1025
@ ID_TAG_EXTRAUSER_SET
Definition DNA_ID.h:884
@ ID_TAG_NO_MAIN
Definition DNA_ID.h:978
#define ID_FAKE_USERS(id)
Definition DNA_ID.h:655
@ ID_RECALC_TRANSFORM
Definition DNA_ID.h:1054
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1118
@ ID_RECALC_TAG_FOR_UNDO
Definition DNA_ID.h:1152
@ ID_RECALC_ANIMATION
Definition DNA_ID.h:1077
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1074
#define ID_IS_OVERRIDE_LIBRARY_REAL(_id)
Definition DNA_ID.h:723
#define ID_IS_LINKED(_id)
Definition DNA_ID.h:694
#define MAX_ID_NAME
Definition DNA_ID.h:373
#define ID_IS_ASSET(_id)
Definition DNA_ID.h:737
#define ID_TYPE_IS_DEPRECATED(id_type)
Definition DNA_ID.h:749
#define ID_IS_EDITABLE(_id)
Definition DNA_ID.h:705
@ INDEX_ID_NULL
Definition DNA_ID.h:1357
#define ID_REAL_USERS(id)
Definition DNA_ID.h:676
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition DNA_ID.h:730
#define ID_NEW_SET(_id, _idn)
Definition DNA_ID.h:756
@ ID_FLAG_INDIRECT_WEAK_LINK
Definition DNA_ID.h:780
@ ID_FLAG_EMBEDDED_DATA_LIB_OVERRIDE
Definition DNA_ID.h:785
@ ID_FLAG_LINKED_AND_PACKED
Definition DNA_ID.h:804
@ ID_FLAG_FAKEUSER
Definition DNA_ID.h:769
@ ID_FLAG_EMBEDDED_DATA
Definition DNA_ID.h:774
@ LIBRARY_FLAG_IS_ARCHIVE
Definition DNA_ID.h:593
#define ID_MISSING(_id)
Definition DNA_ID.h:692
@ ID_WM
@ ID_LI
@ ID_WS
@ ID_NT
@ ID_KE
@ ID_SCE
@ ID_GR
@ ID_OB
#define ID_LINK_PLACEHOLDER
@ POSE_RECALC
Object groups, one object can be in many groups at once.
@ OB_MBALL
@ OB_ARMATURE
eDupli_ID_Flags
@ USER_DUP_LINKED_ID
Read Guarded memory(de)allocation.
#define C
Definition RandGen.cpp:29
Provides wrapper around system-specific atomic primitives, and some extensions (faked-atomic operatio...
ATOMIC_INLINE int32_t atomic_fetch_and_or_int32(int32_t *p, int32_t x)
ATOMIC_INLINE uint32_t atomic_add_and_fetch_uint32(uint32_t *p, uint32_t x)
ATOMIC_INLINE int32_t atomic_fetch_and_and_int32(int32_t *p, int32_t x)
BMesh const char void * data
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
void append(const T &value)
IndexRange index_range() const
void add(ID *old_id, ID *new_id)
#define offsetof(t, d)
#define GS(x)
#define printf(...)
void BKE_id_newptr_and_tag_clear(ID *id)
Definition lib_id.cc:412
ID * BKE_id_owner_get(ID *id, const bool debug_relationship_assert)
Definition lib_id.cc:2511
ID * BKE_libblock_alloc_notest(short type)
Definition lib_id.cc:1340
DEG_id_tag_update_ex(cb_data->bmain, cb_data->owner_id, ID_RECALC_TAG_FOR_UNDO|ID_RECALC_SYNC_TO_EVAL)
void BKE_libblock_init_empty(ID *id)
Definition lib_id.cc:1452
void id_lib_extern(ID *id)
Definition lib_id.cc:290
void BKE_main_id_refcount_recompute(Main *bmain, const bool do_linked_only)
Definition lib_id.cc:2035
void * BKE_id_new_in_lib(Main *bmain, std::optional< Library * > owner_library, const short type, const char *name)
Definition lib_id.cc:1496
void BKE_main_id_repair_duplicate_names_listbase(Main *bmain, ListBase *lb)
Definition lib_id.cc:1258
void BKE_library_make_local(Main *bmain, const Library *lib, GHash *old_to_new_ids, const bool untagged_only, const bool set_fake, const bool clear_asset_data)
Definition lib_id.cc:2129
static int id_copy_libmanagement_cb(LibraryIDLinkCallbackData *cb_data)
Definition lib_id.cc:634
#define ID_SORT_STEP_SIZE
void BKE_libblock_copy_in_lib(Main *bmain, std::optional< Library * > owner_library, const ID *id, std::optional< const ID * > new_owner_id, ID **new_id_p, const int orig_flag)
Definition lib_id.cc:1535
ID * BKE_id_copy_for_use_in_bmain(Main *bmain, const ID *id)
Definition lib_id.cc:851
void BKE_id_tag_clear_atomic(ID *id, int tag)
Definition lib_id.cc:2488
void BKE_lib_id_clear_library_data(Main *bmain, ID *id, const int flags)
Definition lib_id.cc:208
bool id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop)
Definition lib_id.cc:1068
ID * BKE_libblock_find_name(Main *bmain, const short type, const char *name, const std::optional< Library * > lib)
Definition lib_id.cc:1710
void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **new_id_p, const int orig_flag)
Definition lib_id.cc:1694
void BKE_id_full_name_get(char name[MAX_ID_FULL_NAME], const ID *id, char separator_char)
Definition lib_id.cc:2432
ID * BKE_libblock_find_name_and_library(Main *bmain, const short type, const char *name, const char *lib_name)
Definition lib_id.cc:1752
static bool lib_id_library_local_paths_callback(BPathForeachPathData *bpath_data, char *path_dst, size_t path_dst_maxncpy, const char *path_src)
Definition lib_id.cc:129
bool BKE_id_is_editable(const Main *bmain, const ID *id)
Definition lib_id.cc:2523
static int id_refcount_recompute_callback(LibraryIDLinkCallbackData *cb_data)
Definition lib_id.cc:2011
char * BKE_id_to_unique_string_key(const ID *id)
Definition lib_id.cc:2470
void BKE_main_id_flag_listbase(ListBase *lb, const int flag, const bool value)
Definition lib_id.cc:1233
void id_us_plus(ID *id)
Definition lib_id.cc:358
void id_sort_by_name(ListBase *lb, ID *id, ID *id_sorting_hint)
Definition lib_id.cc:1790
bool BKE_id_copy_is_allowed(const ID *id)
Definition lib_id.cc:666
void BKE_main_id_tag_idcode(Main *mainvar, const short type, const int tag, const bool value)
Definition lib_id.cc:1217
void BKE_libblock_management_main_remove(Main *bmain, void *idv)
Definition lib_id.cc:1156
ID * BKE_libblock_find_name_and_library_filepath(Main *bmain, short type, const char *name, const char *lib_filepath_abs)
Definition lib_id.cc:1767
static int libblock_management_us_plus(LibraryIDLinkCallbackData *cb_data)
Definition lib_id.cc:1097
void BKE_lib_id_expand_local(Main *bmain, ID *id, const int flags)
Definition lib_id.cc:481
static void id_swap(Main *bmain, ID *id_a, ID *id_b, const bool do_full_id, const bool do_self_remap, IDRemapper *input_remapper_id_a, IDRemapper *input_remapper_id_b, const int self_remap_flags)
Definition lib_id.cc:913
ID * BKE_id_copy_ex(Main *bmain, const ID *id, ID **new_id_p, const int flag)
Definition lib_id.cc:777
void BKE_id_tag_set_atomic(ID *id, int tag)
Definition lib_id.cc:2483
void BKE_id_move_to_same_lib(Main &bmain, ID &id, const ID &owner_id)
Definition lib_id.cc:879
bool BKE_id_can_use_id(const ID &id_from, const ID &id_to)
Definition lib_id.cc:2528
#define LIB_ID_TYPES_NOCOPY
void id_fake_user_set(ID *id)
Definition lib_id.cc:396
void BKE_lib_id_swap(Main *bmain, ID *id_a, ID *id_b, const bool do_self_remap, const int self_remap_flags)
Definition lib_id.cc:1056
void BKE_id_reorder(const ListBase *lb, ID *id, ID *relative, bool after)
Definition lib_id.cc:2595
void * BKE_libblock_copy(Main *bmain, const ID *id)
Definition lib_id.cc:1699
void BKE_id_full_name_ui_prefix_get(char name[MAX_ID_FULL_NAME_UI], const ID *id, const bool add_lib_hint, char separator_char, int *r_prefix_len)
Definition lib_id.cc:2449
IDNewNameResult BKE_libblock_rename(Main &bmain, ID &id, blender::StringRefNull name, const IDNewNameMode mode)
Definition lib_id.cc:2370
void BKE_main_id_flag_all(Main *bmain, const int flag, const bool value)
Definition lib_id.cc:1249
static int lib_id_expand_local_cb(LibraryIDLinkCallbackData *cb_data)
Definition lib_id.cc:442
bool BKE_id_is_in_main(Main *bmain, ID *id)
Definition lib_id.cc:2493
void BKE_libblock_runtime_reset_remapping_status(ID *id)
Definition lib_id.cc:1466
void BKE_main_id_newptr_and_tag_clear(Main *bmain)
Definition lib_id.cc:2001
void BKE_lib_libblock_session_uid_ensure(ID *id)
Definition lib_id.cc:1477
void * BKE_id_new_nomain(const short type, const char *name)
Definition lib_id.cc:1519
void id_us_ensure_real(ID *id)
Definition lib_id.cc:313
void BKE_lib_id_make_local_generic(Main *bmain, ID *id, const int flags)
Definition lib_id.cc:544
void id_fake_user_clear(ID *id)
Definition lib_id.cc:404
void id_us_clear_real(ID *id)
Definition lib_id.cc:331
void BKE_lib_id_swap_full(Main *bmain, ID *id_a, ID *id_b, const bool do_self_remap, const int self_remap_flags)
Definition lib_id.cc:1062
void BKE_libblock_management_usercounts_set(Main *bmain, void *idv)
Definition lib_id.cc:1176
void BKE_lib_id_make_local_generic_action_define(Main *bmain, ID *id, int flags, bool *r_force_local, bool *r_force_copy)
Definition lib_id.cc:502
void BKE_main_lib_objects_recalc_all(Main *bmain)
Definition lib_id.cc:1290
ID * BKE_id_copy(Main *bmain, const ID *id)
Definition lib_id.cc:782
void id_us_plus_no_lib(ID *id)
Definition lib_id.cc:342
static void library_make_local_copying_check(ID *id, GSet *loop_tags, MainIDRelations *id_relations, GSet *done_ids)
Definition lib_id.cc:2067
void BKE_main_id_tag_listbase(ListBase *lb, const int tag, const bool value)
Definition lib_id.cc:1201
void lib_id_copy_ensure_local(Main *bmain, const ID *old_id, ID *new_id, const int flags)
Definition lib_id.cc:487
void BKE_main_id_tag_all(Main *mainvar, const int tag, const bool value)
Definition lib_id.cc:1224
static void id_embedded_swap(Main *bmain, ID **embedded_id_a, ID **embedded_id_b, const bool do_full_id, IDRemapper *remapper_id_a, IDRemapper *remapper_id_b)
Definition lib_id.cc:1023
void id_lib_indirect_weak_link(ID *id)
Definition lib_id.cc:303
bool BKE_lib_id_make_local(Main *bmain, ID *id, const int flags)
Definition lib_id.cc:598
void * BKE_id_new(Main *bmain, const short type, const char *name)
Definition lib_id.cc:1514
void BKE_libblock_runtime_ensure(ID &id)
Definition lib_id.cc:1316
void id_us_min(ID *id)
Definition lib_id.cc:366
static int * id_order_get(ID *id)
Definition lib_id.cc:2544
void * BKE_libblock_alloc_in_lib(Main *bmain, std::optional< Library * > owner_library, short type, const char *name, const int flag)
Definition lib_id.cc:1352
static uint global_session_uid
Definition lib_id.cc:1475
Vector< ID * > BKE_id_ordered_list(const ListBase *lb)
Definition lib_id.cc:2576
void * BKE_libblock_alloc(Main *bmain, short type, const char *name, const int flag)
Definition lib_id.cc:1447
IDNewNameResult BKE_id_new_name_validate(Main &bmain, ListBase &lb, ID &id, const char *newname, IDNewNameMode mode, const bool do_linked_data)
Definition lib_id.cc:1903
ID * BKE_id_copy_in_lib(Main *bmain, std::optional< Library * > owner_library, const ID *id, std::optional< const ID * > new_owner_id, ID **new_id_p, const int flag)
Definition lib_id.cc:675
static int libblock_management_us_min(LibraryIDLinkCallbackData *cb_data)
Definition lib_id.cc:1111
ID * BKE_libblock_find_session_uid(Main *bmain, const short type, const uint32_t session_uid)
Definition lib_id.cc:1728
void BKE_id_blend_write(BlendWriter *writer, ID *id)
Definition lib_id.cc:2631
void BKE_libblock_management_main_add(Main *bmain, void *idv)
Definition lib_id.cc:1123
ID * BKE_id_copy_for_duplicate(Main *bmain, ID *id, const eDupli_ID_Flags duplicate_flags, const int copy_flags)
Definition lib_id.cc:787
void BKE_libblock_management_usercounts_clear(Main *bmain, void *idv)
Definition lib_id.cc:1188
static bool id_order_compare(ID *a, ID *b)
Definition lib_id.cc:2555
static int foreach_assign_id_to_orig_callback(LibraryIDLinkCallbackData *cb_data)
Definition lib_id.cc:826
size_t BKE_libblock_get_alloc_info(short type, const char **r_name)
Definition lib_id.cc:1323
bool BKE_id_can_be_asset(const ID *id)
Definition lib_id.cc:2505
IDNewNameResult BKE_id_rename(Main &bmain, ID &id, blender::StringRefNull name, const IDNewNameMode mode)
Definition lib_id.cc:2392
bool BKE_id_is_in_global_main(ID *id)
Definition lib_id.cc:2500
void BKE_lib_libblock_session_uid_renew(ID *id)
Definition lib_id.cc:1490
#define LOG(level)
Definition log.h:97
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
void action_slots_user_cache_invalidate(Main &bmain)
bNodeTree ** node_tree_ptr_from_id(ID *id)
Definition node.cc:4543
bNodeTree * node_tree_from_id(ID *id)
Definition node.cc:4568
const char * name
void RNA_property_pointer_set(PointerRNA *ptr, PropertyRNA *prop, PointerRNA ptr_value, ReportList *reports)
void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
bool RNA_property_editable(const PointerRNA *ptr, PropertyRNA *prop)
PointerRNA RNA_id_pointer_create(ID *id)
OnClearAssetDataFn on_clear_asset_fn
Definition BKE_asset.hh:39
eBPathForeachFlag flag
Definition BKE_bpath.hh:102
BPathForeachPathFunctionCallback callback_function
Definition BKE_bpath.hh:101
const char * name
IDTypeCopyDataFunction copy_data
IDTypeInitDataFunction init_data
uint32_t flags
size_t struct_size
IDTypeMakeLocalFunction make_local
AssetTypeInfo * asset_type_info
IDTypeEmbeddedOwnerPointerGetFunction owner_pointer_get
Definition DNA_ID.h:414
unsigned int recalc
Definition DNA_ID.h:445
int tag
Definition DNA_ID.h:442
struct AssetMetaData * asset_data
Definition DNA_ID.h:423
struct Library * lib
Definition DNA_ID.h:420
char name[258]
Definition DNA_ID.h:432
IDProperty * system_properties
Definition DNA_ID.h:489
int us
Definition DNA_ID.h:443
struct ID * newid
Definition DNA_ID.h:418
void * prev
Definition DNA_ID.h:417
IDProperty * properties
Definition DNA_ID.h:480
short flag
Definition DNA_ID.h:438
void * next
Definition DNA_ID.h:417
IDHash deep_hash
Definition DNA_ID.h:474
unsigned int session_uid
Definition DNA_ID.h:462
struct LibraryWeakReference * library_weak_reference
Definition DNA_ID.h:526
LibraryForeachIDCallbackFlag cb_flag
LibraryRuntimeHandle * runtime
Definition DNA_ID.h:579
struct LinkNode * next
void * last
void * first
MainIDRelationsEntryItem * next
Definition BKE_main.hh:58
MainIDRelationsEntryItem * from_ids
Definition BKE_main.hh:75
GHash * relations_from_pointers
Definition BKE_main.hh:130
bool is_locked_for_linking
Definition BKE_main.hh:224
bool is_memfile_undo_written
Definition BKE_main.hh:208
Library * curlib
Definition BKE_main.hh:269
MainIDRelations * relations
Definition BKE_main.hh:329
ListBase objects
Definition BKE_main.hh:280
struct Collection * master_collection
i
Definition text_draw.cc:230
#define N_(msgid)
static DynamicLibrary lib
PointerRNA * ptr
Definition wm_files.cc:4238
uint8_t flag
Definition wm_window.cc:145