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