Blender V5.0
library.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
10
11#include <optional>
12
13#include "CLG_log.h"
14
15/* all types are needed here, in order to do memory operations */
16#include "DNA_ID.h"
18#include "DNA_scene_types.h"
19
20#include "BLI_utildefines.h"
21
22#include "BLI_ghash.h"
23#include "BLI_listbase.h"
24#include "BLI_path_utils.hh"
25#include "BLI_set.hh"
26#include "BLI_string.h"
27#include "BLI_vector_set.hh"
28
29#include "BLT_translation.hh"
30
31#include "BLO_read_write.hh"
32
33#include "BKE_bpath.hh"
34#include "BKE_id_hash.hh"
35#include "BKE_idtype.hh"
36#include "BKE_key.hh"
37#include "BKE_lib_id.hh"
38#include "BKE_lib_query.hh"
39#include "BKE_lib_remap.hh"
40#include "BKE_library.hh"
41#include "BKE_main.hh"
43#include "BKE_main_namemap.hh"
44#include "BKE_node.hh"
45#include "BKE_packedFile.hh"
46#include "BKE_report.hh"
47
48struct BlendDataReader;
49
50static CLG_LogRef LOG = {"lib.library"};
51
52using namespace blender::bke;
53using namespace blender::bke::library;
54
56{
57 BKE_main_namemap_destroy(&lib->runtime->name_map);
58}
59
60static void library_init_data(ID *id)
61{
62 Library *library = reinterpret_cast<Library *>(id);
63 library->runtime = MEM_new<LibraryRuntime>(__func__);
64}
65
66static void library_free_data(ID *id)
67{
68 Library *library = (Library *)id;
70 MEM_delete(library->runtime);
71 if (library->packedfile) {
72 BKE_packedfile_free(library->packedfile);
73 }
74}
75
76static void library_copy_data(Main *bmain,
77 std::optional<Library *> owner_library,
78 ID *id_dst,
79 const ID *id_src,
80 int /*flag*/)
81{
82 /* Libraries are always local IDs. */
83 BLI_assert(!owner_library || *owner_library == nullptr);
84 UNUSED_VARS_NDEBUG(bmain, owner_library);
85
86 const Library *library_src = reinterpret_cast<const Library *>(id_src);
87
88 /* Libraries are copyable now, but there should still be only one library ID for each linked
89 * blendfile (based on absolute filepath). */
90 BLI_assert(!bmain ||
91 !search_filepath_abs(&bmain->libraries, library_src->runtime->filepath_abs));
92
93 Library *library_dst = reinterpret_cast<Library *>(id_dst);
94 if (library_src->packedfile) {
95 library_dst->packedfile = BKE_packedfile_duplicate(library_src->packedfile);
96 }
97
98 /* Only explicitely copy a sub-set of the runtime data. */
99 library_dst->runtime = MEM_new<LibraryRuntime>(__func__);
100 BLI_strncpy(library_dst->runtime->filepath_abs,
101 library_src->runtime->filepath_abs,
102 sizeof(library_dst->runtime->filepath_abs));
103 library_dst->runtime->parent = library_src->runtime->parent;
104 library_dst->runtime->tag = library_src->runtime->tag;
105 library_dst->runtime->versionfile = library_src->runtime->versionfile;
106 library_dst->runtime->subversionfile = library_src->runtime->subversionfile;
107 library_dst->runtime->colorspace = library_src->runtime->colorspace;
108}
109
111{
112 Library *lib = (Library *)id;
115
116 if (lib->flag & LIBRARY_FLAG_IS_ARCHIVE) {
117 /* Archive library must have a parent, this can't be nullptr. */
118 if (lib->archive_parent_library) {
120 data, lib->archive_parent_library, IDWALK_CB_NEVER_SELF | IDWALK_CB_NEVER_NULL);
121 }
122
123 /* Archive libraries should never 'own' other archives. */
124 BLI_assert(lib->runtime->archived_libraries.is_empty());
125 if (foreach_flag & IDWALK_DO_INTERNAL_RUNTIME_POINTERS) {
126 for (Library *&lib_p : lib->runtime->archived_libraries) {
129 }
130 }
131 }
132 else {
133 /* Regular libraries should never have an archive parent. */
134 BLI_assert(!lib->archive_parent_library);
136
137 if (foreach_flag & IDWALK_DO_INTERNAL_RUNTIME_POINTERS) {
138 for (Library *&lib_p : lib->runtime->archived_libraries) {
141 }
142 }
143 }
144}
145
146static void library_foreach_path(ID *id, BPathForeachPathData *bpath_data)
147{
148 Library *lib = (Library *)id;
149
150 /* FIXME: Find if we should respect #BKE_BPATH_FOREACH_PATH_SKIP_PACKED here, and if not, explain
151 * why. */
152 if (lib->packedfile !=
153 nullptr /*&& (bpath_data->flag & BKE_BPATH_FOREACH_PATH_SKIP_PACKED) != 0 */)
154 {
155 return;
156 }
157
158 if (BKE_bpath_foreach_path_fixed_process(bpath_data, lib->filepath, sizeof(lib->filepath))) {
159 BKE_library_filepath_set(bpath_data->bmain, lib, lib->filepath);
160 }
161}
162
163static void library_blend_write_data(BlendWriter *writer, ID *id, const void *id_address)
164{
165 Library *library = reinterpret_cast<Library *>(id);
166 const bool is_undo = BLO_write_is_undo(writer);
167
168 /* Clear runtime data. */
169 library->runtime = nullptr;
170
171 BLO_write_id_struct(writer, Library, id_address, id);
172 BKE_id_blend_write(writer, id);
173
174 /* Write packed file if necessary. */
175 if (library->packedfile) {
176 BKE_packedfile_blend_write(writer, library->packedfile);
177 if (!is_undo) {
178 CLOG_DEBUG(&LOG, "Write packed .blend: %s", library->filepath);
179 }
180 }
181}
182
183static void library_blend_read_data(BlendDataReader * /*reader*/, ID *id)
184{
185 Library *lib = reinterpret_cast<Library *>(id);
186 lib->runtime = MEM_new<LibraryRuntime>(__func__);
187}
188
190{
191 Library *lib = reinterpret_cast<Library *>(id);
192 if (lib->flag & LIBRARY_FLAG_IS_ARCHIVE) {
193 BLI_assert(lib->archive_parent_library);
194 lib->archive_parent_library->runtime->archived_libraries.append(lib);
195 }
196}
197
199 /*id_code*/ Library::id_type,
200 /*id_filter*/ FILTER_ID_LI,
201 /*dependencies_id_types*/ FILTER_ID_LI,
202 /*main_listbase_index*/ INDEX_ID_LI,
203 /*struct_size*/ sizeof(Library),
204 /*name*/ "Library",
205 /*name_plural*/ N_("libraries"),
206 /*translation_context*/ BLT_I18NCONTEXT_ID_LIBRARY,
208 /*asset_type_info*/ nullptr,
209
210 /*init_data*/ library_init_data,
211 /*copy_data*/ library_copy_data,
212 /*free_data*/ library_free_data,
213 /*make_local*/ nullptr,
214 /*foreach_id*/ library_foreach_id,
215 /*foreach_cache*/ nullptr,
216 /*foreach_path*/ library_foreach_path,
217 /*foreach_working_space_color*/ nullptr,
218 /*owner_pointer_get*/ nullptr,
219
220 /*blend_write*/ library_blend_write_data,
221 /*blend_read_data*/ library_blend_read_data,
222 /*blend_read_after_liblink*/ library_blend_read_after_liblink,
223
224 /*blend_read_undo_preserve*/ nullptr,
225
226 /*lib_override_apply_post*/ nullptr,
227};
228
229void BKE_library_filepath_set(Main *bmain, Library *lib, const char *filepath)
230{
231 /* in some cases this is used to update the absolute path from the
232 * relative */
233 if (lib->filepath != filepath) {
234 STRNCPY(lib->filepath, filepath);
235 }
236
237 STRNCPY(lib->runtime->filepath_abs, filepath);
238
239 /* Not essential but set `filepath_abs` is an absolute copy of value which
240 * is more useful if its kept in sync. */
241 if (BLI_path_is_rel(lib->runtime->filepath_abs)) {
242 /* NOTE(@ideasman42): the file may be unsaved, in this case, setting the
243 * `filepath_abs` on an indirectly linked path is not allowed from the
244 * outliner, and its not really supported but allow from here for now
245 * since making local could cause this to be directly linked.
246 */
247 /* Never make paths relative to parent lib - reading code (blenloader) always set *all*
248 * `lib->filepath` relative to current main, not to their parent for indirectly linked ones. */
249 const char *blendfile_path = BKE_main_blendfile_path(bmain);
250 BLI_path_abs(lib->runtime->filepath_abs, blendfile_path);
251 }
252}
253
255 blender::Set<Library *> &directly_used_libs,
256 Library *lib)
257{
258 BLI_assert(!directly_used_libs.contains(lib));
259
260 Library *best_parent_lib = nullptr;
261 bool do_break = false;
262 ListBase *lb;
263 ID *id_iter;
264 FOREACH_MAIN_LISTBASE_BEGIN (bmain, lb) {
265 FOREACH_MAIN_LISTBASE_ID_BEGIN (lb, id_iter) {
266 if (!ID_IS_LINKED(id_iter) || id_iter->lib != lib) {
267 continue;
268 }
269 MainIDRelationsEntry *entry = static_cast<MainIDRelationsEntry *>(
271 for (MainIDRelationsEntryItem *item = entry->from_ids; item; item = item->next) {
272 ID *from_id = item->id_pointer.from;
273 if (!ID_IS_LINKED(from_id)) {
275 continue;
276 }
277 Library *from_id_lib = from_id->lib;
278 if (from_id_lib == lib) {
279 continue;
280 }
281 if (directly_used_libs.contains(from_id_lib)) {
282 /* Found the first best possible candidate, no need to search further. */
283 BLI_assert(best_parent_lib == nullptr || best_parent_lib->runtime->temp_index > 0);
284 best_parent_lib = from_id_lib;
285 do_break = true;
286 break;
287 }
288 if (!from_id_lib->runtime->parent) {
289 rebuild_hierarchy_best_parent_find(bmain, directly_used_libs, from_id_lib);
290 }
291 if (!best_parent_lib ||
292 best_parent_lib->runtime->temp_index > from_id_lib->runtime->temp_index)
293 {
294 best_parent_lib = from_id_lib;
295 if (best_parent_lib->runtime->temp_index == 0) {
296 /* Found the first best possible candidate, no need to search further. */
297 BLI_assert(directly_used_libs.contains(best_parent_lib));
298 do_break = true;
299 break;
300 }
301 }
302 }
303 if (do_break) {
304 break;
305 }
306 }
308 if (do_break) {
309 break;
310 }
311 }
313
314 /* NOTE: It may happen that no parent library is found, e.g. if after deleting a directly used
315 * library, its indirect dependency is still around, but none of its linked IDs are used by local
316 * data. */
317 if (best_parent_lib) {
318 lib->runtime->parent = best_parent_lib;
319 lib->runtime->temp_index = best_parent_lib->runtime->temp_index + 1;
320 }
321 else {
322 lib->runtime->parent = nullptr;
323 lib->runtime->temp_index = 0;
324 directly_used_libs.add(lib);
325 }
326}
327
329{
331
332 /* Reset all values, they may have been set to irrelevant values by other processes (like the
333 * liboverride handling e.g., see #lib_override_libraries_index_define). */
334 LISTBASE_FOREACH (Library *, lib_iter, &bmain->libraries) {
335 lib_iter->runtime->temp_index = 0;
336 }
337
338 /* Find all libraries with directly linked IDs (i.e. IDs used by local data). */
339 blender::Set<Library *> directly_used_libs;
340 ID *id_iter;
341 FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
342 if (!ID_IS_LINKED(id_iter)) {
343 continue;
344 }
345 id_iter->lib->runtime->temp_index = 0;
346 if (directly_used_libs.contains(id_iter->lib)) {
347 continue;
348 }
349 MainIDRelationsEntry *entry = static_cast<MainIDRelationsEntry *>(
351 for (MainIDRelationsEntryItem *item = entry->from_ids; item; item = item->next) {
352 if (!ID_IS_LINKED(item->id_pointer.from)) {
353 directly_used_libs.add(id_iter->lib);
354 id_iter->lib->runtime->parent = nullptr;
355 break;
356 }
357 }
358 }
360
361 LISTBASE_FOREACH (Library *, lib_iter, &bmain->libraries) {
362 /* A directly used library. */
363 if (directly_used_libs.contains(lib_iter)) {
364 BLI_assert(lib_iter->runtime->temp_index == 0);
365 continue;
366 }
367
368 /* Assume existing parent is still valid, since it was not cleared in previous loop above.
369 * Just compute 'hierarchy value' in temp index, if needed. */
370 if (lib_iter->runtime->parent) {
371 if (lib_iter->runtime->temp_index > 0) {
372 continue;
373 }
374 blender::Vector<Library *> parent_libraries;
375 for (Library *parent_lib_iter = lib_iter;
376 parent_lib_iter && parent_lib_iter->runtime->temp_index == 0;
377 parent_lib_iter = parent_lib_iter->runtime->parent)
378 {
379 parent_libraries.append(parent_lib_iter);
380 }
381 int parent_temp_index = parent_libraries.last()->runtime->temp_index +
382 int(parent_libraries.size()) - 1;
383 for (Library *parent_lib_iter : parent_libraries) {
384 BLI_assert(parent_lib_iter != parent_libraries.last() ||
385 parent_lib_iter->runtime->temp_index == parent_temp_index);
386 parent_lib_iter->runtime->temp_index = parent_temp_index--;
387 }
388 continue;
389 }
390
391 /* Otherwise, it's an indirectly used library with no known parent, another loop is needed to
392 * ensure all known hierarchy has valid indices when trying to find the best valid parent
393 * library. */
394 }
395
396 /* For all libraries known to be indirect, but without a known parent, find a best valid parent
397 * (i.e. a 'most directly used' library). */
398 LISTBASE_FOREACH (Library *, lib_iter, &bmain->libraries) {
399 /* A directly used library. */
400 if (directly_used_libs.contains(lib_iter)) {
401 BLI_assert(lib_iter->runtime->temp_index == 0);
402 continue;
403 }
404
405 if (lib_iter->runtime->parent) {
406 BLI_assert(lib_iter->runtime->temp_index > 0);
407 }
408 else {
409 BLI_assert(lib_iter->runtime->temp_index == 0);
410 rebuild_hierarchy_best_parent_find(bmain, directly_used_libs, lib_iter);
411 }
412 }
413
415}
416
418 blender::StringRef filepath_abs)
419{
420 LISTBASE_FOREACH (Library *, lib_iter, libraries) {
421 if (lib_iter->flag & LIBRARY_FLAG_IS_ARCHIVE) {
422 /* Skip archive libraries because there may be multiple of those for the same path and there
423 * should also be a non-archive one. */
424 continue;
425 }
426 if (filepath_abs == lib_iter->runtime->filepath_abs) {
427 return lib_iter;
428 }
429 }
430 return nullptr;
431}
432
436static Library *add_archive_library(Main &bmain, Library &reference_library)
437{
438 BLI_assert((reference_library.flag & LIBRARY_FLAG_IS_ARCHIVE) == 0);
439 /* Cannot copy libraries using generic ID copying functions, so create the copy manually. */
440 Library *archive_library = static_cast<Library *>(
441 BKE_id_new(&bmain, ID_LI, BKE_id_name(reference_library.id)));
442
443 /* Like in #direct_link_library. */
444 id_us_ensure_real(&archive_library->id);
445
446 archive_library->archive_parent_library = &reference_library;
447 constexpr uint16_t copy_flag = ~LIBRARY_FLAG_IS_ARCHIVE;
448 archive_library->flag = (reference_library.flag & copy_flag) | LIBRARY_FLAG_IS_ARCHIVE;
449 BKE_library_filepath_set(&bmain, archive_library, reference_library.filepath);
450
451 archive_library->runtime->parent = reference_library.runtime->parent;
452 /* Only copy a subset of the reference library tags. E.g. an archive library should never be
453 * considered as writable, so never copy #LIBRARY_ASSET_FILE_WRITABLE. This may need further
454 * tweaking still. */
455 constexpr uint16_t copy_tag = (LIBRARY_TAG_RESYNC_REQUIRED | LIBRARY_ASSET_EDITABLE |
457 archive_library->runtime->tag = reference_library.runtime->tag & copy_tag;
458 /* By definition, the file version of an archive library containing only packed linked data is
459 * the same as the one of its Main container. */
460 archive_library->runtime->versionfile = bmain.versionfile;
461 archive_library->runtime->subversionfile = bmain.subversionfile;
462
463 reference_library.runtime->archived_libraries.append(archive_library);
464
465 return archive_library;
466}
467
469 Main &bmain, ID &id, Library &reference_library, const IDHash &id_deep_hash, bool &is_new)
470{
472 BLI_assert((reference_library.flag & LIBRARY_FLAG_IS_ARCHIVE) == 0);
473
474 Library *archive_library = nullptr;
475 for (Library *lib_iter : reference_library.runtime->archived_libraries) {
476 BLI_assert((lib_iter->flag & LIBRARY_FLAG_IS_ARCHIVE) != 0);
477 BLI_assert(lib_iter->archive_parent_library != nullptr);
478 BLI_assert(lib_iter->archive_parent_library == &reference_library);
479 /* Check if current archive library already contains an ID of same type and name. */
480 if (BKE_main_namemap_contain_name(bmain, lib_iter, GS(id.name), BKE_id_name(id))) {
481#ifndef NDEBUG
483 &bmain, GS(id.name), BKE_id_name(id), BKE_id_name(lib_iter->id));
485 packed_id && packed_id->deep_hash != id_deep_hash,
486 "An already packed ID with same deep hash as the one to be packed, should have already "
487 "be found and used (deduplication) before reaching this code-path");
488#endif
489 UNUSED_VARS_NDEBUG(id_deep_hash);
490 continue;
491 }
492 archive_library = lib_iter;
493 break;
494 }
495 if (!archive_library) {
496 archive_library = add_archive_library(bmain, reference_library);
497 is_new = true;
498 }
499 else {
500 is_new = false;
501 }
502 BLI_assert(reference_library.runtime->archived_libraries.contains(archive_library));
503 return archive_library;
504}
505
506static void pack_linked_id(Main &bmain,
507 ID *linked_id,
508 const id_hash::ValidDeepHashes &deep_hashes,
509 blender::Map<IDHash, ID *> &already_packed_ids,
510 blender::VectorSet<ID *> &ids_to_remap,
511 blender::bke::id::IDRemapper &id_remapper)
512{
513 BLI_assert(linked_id->newid == nullptr);
514
515 const IDHash linked_id_deep_hash = deep_hashes.hashes.lookup(linked_id);
516 ID *packed_id = already_packed_ids.lookup_default(linked_id_deep_hash, nullptr);
517
518 if (packed_id) {
519 /* Exact same ID (and all of its dependencies) have already been linked and packed before,
520 * re-use these packed data. */
521
522 auto existing_id_process = [&deep_hashes, &id_remapper](ID *linked_id, ID *packed_id) {
523 BLI_assert(packed_id);
524 BLI_assert(ID_IS_PACKED(packed_id));
525 /* Note: linked_id and packed_id may have the same deep hash while still coming from
526 * different original libraries. This easily happens copying an asset file such that each
527 * asset exists twice. */
528 BLI_assert(packed_id->deep_hash == deep_hashes.hashes.lookup(linked_id));
529 UNUSED_VARS_NDEBUG(deep_hashes);
530
531 id_remapper.add(linked_id, packed_id);
532 linked_id->newid = packed_id;
533 /* No need to remap this packed ID - otherwise there would be something very wrong in
534 * packed IDs state. */
535 };
536
537 existing_id_process(linked_id, packed_id);
538
539 /* Handle 'fake-embedded' ShapeKeys IDs. */
540 Key *linked_key = BKE_key_from_id(linked_id);
541 if (linked_key) {
542 Key *packed_key = BKE_key_from_id(packed_id);
543 BLI_assert(packed_key);
544 existing_id_process(&linked_key->id, &packed_key->id);
545 }
546 }
547 else {
548 /* This exact version of the ID and its dependencies have not been packed before, creates a
549 * new copy of it and pack it. */
550
551 /* Find an existing archive Library not containing a 'version' of this ID yet (to prevent names
552 * collisions). */
553 bool is_new;
554 Library *archive_lib = ensure_archive_library(
555 bmain, *linked_id, *linked_id->lib, linked_id_deep_hash, is_new);
556
557 auto copied_id_process =
558 [&archive_lib, &deep_hashes, &ids_to_remap, &id_remapper, &already_packed_ids](
559 ID *linked_id, ID *packed_id) {
560 BLI_assert(packed_id);
561 BLI_assert(ID_IS_PACKED(packed_id));
562 BLI_assert(packed_id->lib == archive_lib);
563 UNUSED_VARS_NDEBUG(archive_lib);
564
565 if (GS(packed_id->name) == ID_SCE) {
566 /* Like in #scene_blend_read_data. */
567 id_us_ensure_real(packed_id);
568 }
569
570 packed_id->deep_hash = deep_hashes.hashes.lookup(linked_id);
571 id_remapper.add(linked_id, packed_id);
572 ids_to_remap.add(packed_id);
573 already_packed_ids.add(packed_id->deep_hash, packed_id);
574 };
575
576 packed_id = BKE_id_copy_in_lib(&bmain,
577 archive_lib,
578 linked_id,
579 std::nullopt,
580 nullptr,
583 id_us_min(packed_id);
584 copied_id_process(linked_id, packed_id);
585
586 /* Handle 'fake-embedded' ShapeKeys IDs. */
587 Key *linked_key = BKE_key_from_id(linked_id);
588 if (linked_key) {
589 Key *embedded_key = BKE_key_from_id(packed_id);
590 BLI_assert(embedded_key);
591 copied_id_process(&linked_key->id, &embedded_key->id);
592 }
593 }
594}
595
601static void pack_linked_ids(Main &bmain, const blender::Set<ID *> &ids_to_pack)
602{
603 blender::VectorSet<ID *> final_ids_to_pack;
604 blender::VectorSet<ID *> ids_to_remap;
606
607 for (ID *id : ids_to_pack) {
609 if (ID_IS_PACKED(id)) {
610 /* Should not happen, but also not critical issue. */
612 "Trying to pack an already packed ID '%s' (from '%s')",
613 id->name,
614 id->lib->runtime->filepath_abs);
615 /* Already packed. */
616 continue;
617 }
618 final_ids_to_pack.add(id);
619 }
620
622 bmain, final_ids_to_pack.as_span());
623 if (const auto *errors = std::get_if<id_hash::DeepHashErrors>(&hash_result)) {
624 if (!errors->missing_files.is_empty()) {
626 "Trying to pack IDs that depend on missing linked libraries: %s",
627 errors->missing_files[0].c_str());
628 }
629 if (!errors->updated_files.is_empty()) {
631 "Trying to pack linked ID that has been modified on disk: %s",
632 errors->updated_files[0].c_str());
633 }
634 return;
635 }
636 const auto &deep_hashes = std::get<id_hash::ValidDeepHashes>(hash_result);
637
638 blender::Map<IDHash, ID *> already_packed_ids;
639 {
640 ID *id;
641 FOREACH_MAIN_ID_BEGIN (&bmain, id) {
642 if (ID_IS_PACKED(id)) {
643 already_packed_ids.add(id->deep_hash, id);
644 }
645 }
647 }
648
649 for (ID *linked_id : final_ids_to_pack) {
650 pack_linked_id(bmain, linked_id, deep_hashes, already_packed_ids, ids_to_remap, id_remapper);
651 }
652
654 &bmain, ids_to_remap.as_span(), ID_REMAP_TYPE_REMAP, id_remapper, 0);
656}
657
659{
660 BLI_assert(ID_IS_LINKED(&root_id));
661 BLI_assert(!ID_IS_PACKED(&root_id));
662
663 blender::Set<ID *> ids_to_pack;
664 ids_to_pack.add(&root_id);
666 &bmain,
667 &root_id,
668 [&ids_to_pack](LibraryIDLinkCallbackData *cb_data) -> int {
669 if (cb_data->cb_flag & IDWALK_CB_LOOPBACK) {
670 return IDWALK_RET_NOP;
671 }
673 return IDWALK_RET_NOP;
674 }
675
676 ID *self_id = cb_data->self_id;
677 ID *referenced_id = *cb_data->id_pointer;
678 if (!referenced_id) {
679 return IDWALK_RET_NOP;
680 }
681 if (!ID_IS_LINKED(referenced_id)) {
682 CLOG_ERROR(&LOG, "Linked data-block references non-linked data-block");
683 return IDWALK_RET_NOP;
684 }
685 if (ID_IS_PACKED(referenced_id)) {
686 /* A linked ID can use another packed linked ID, as long as it is not from the same
687 * library. */
688 BLI_assert(referenced_id->lib && referenced_id->lib->archive_parent_library);
689 if (referenced_id->lib->archive_parent_library == self_id->lib) {
691 "Non-packed data-block references packed data-block from the same library, "
692 "which is not allowed");
693 }
694 return IDWALK_RET_NOP;
695 }
696 if (referenced_id->newid && ID_IS_PACKED(referenced_id->newid)) {
697 return IDWALK_RET_NOP;
698 }
699 if (GS(referenced_id->name) == ID_KE) {
700 /* Shape keys cannot be directly linked, from linking code PoV they behave as embedded
701 * data (i.e. their owning data is responsible to handle them). */
702 return IDWALK_RET_NOP;
703 }
704
705 ids_to_pack.add(referenced_id);
706 return IDWALK_RET_NOP;
707 },
708 nullptr,
710
711 pack_linked_ids(bmain, ids_to_pack);
712}
713
715{
717 if (lib->flag & LIBRARY_FLAG_IS_ARCHIVE) {
718 BLI_assert(!lib->runtime || lib->runtime->archived_libraries.is_empty());
719 }
720 else {
721 int i_read_curr = 0;
722 int i_insert_curr = 0;
723 for (; i_read_curr < lib->runtime->archived_libraries.size(); i_read_curr++) {
724 if (!lib->runtime->archived_libraries[i_read_curr]) {
725 continue;
726 }
727 if (i_insert_curr < i_read_curr) {
728 lib->runtime->archived_libraries[i_insert_curr] =
729 lib->runtime->archived_libraries[i_read_curr];
730 }
731 i_insert_curr++;
732 }
733 BLI_assert(i_insert_curr <= i_read_curr);
734 if (i_insert_curr < i_read_curr) {
735 lib->runtime->archived_libraries.resize(i_insert_curr);
736 }
737 }
738 }
739}
bool BKE_bpath_foreach_path_fixed_process(BPathForeachPathData *bpath_data, char *path, size_t path_maxncpy)
Definition bpath.cc:125
@ IDTYPE_FLAGS_NO_ANIMDATA
Definition BKE_idtype.hh:49
@ IDTYPE_FLAGS_NO_LIBLINKING
Definition BKE_idtype.hh:35
@ IDTYPE_FLAGS_NEVER_UNUSED
Definition BKE_idtype.hh:72
IDTypeInfo IDType_ID_LI
Definition library.cc:198
Key * BKE_key_from_id(ID *id)
Definition key.cc:1771
struct 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, int flag)
Definition lib_id.cc:675
ID * BKE_libblock_find_name_and_library(Main *bmain, short type, const char *name, const char *lib_name)
Definition lib_id.cc:1752
void id_us_ensure_real(ID *id)
Definition lib_id.cc:313
void * BKE_id_new(Main *bmain, short type, const char *name)
Definition lib_id.cc:1514
@ LIB_ID_COPY_ASSET_METADATA
@ LIB_ID_COPY_ID_NEW_SET
@ LIB_ID_COPY_NO_ANIMDATA
@ LIB_ID_COPY_DEFAULT
const char * BKE_id_name(const ID &id)
void id_us_min(ID *id)
Definition lib_id.cc:366
void BKE_id_blend_write(BlendWriter *writer, ID *id)
Definition lib_id.cc:2631
@ IDWALK_RET_NOP
#define BKE_LIB_FOREACHID_PROCESS_IDSUPER(data_, id_super_, cb_flag_)
@ IDWALK_CB_LOOPBACK
@ IDWALK_CB_NEVER_SELF
@ IDWALK_CB_INTERNAL
@ IDWALK_CB_EMBEDDED_NOT_OWNING
@ IDWALK_CB_EMBEDDED
@ IDWALK_CB_NEVER_NULL
#define BKE_LIB_FOREACHID_PROCESS_ID(data_, id_, cb_flag_)
LibraryForeachIDFlag BKE_lib_query_foreachid_process_flags_get(const LibraryForeachIDData *data)
Definition lib_query.cc:129
void BKE_library_foreach_ID_link(Main *bmain, ID *id, blender::FunctionRef< LibraryIDLinkCallback > callback, void *user_data, LibraryForeachIDFlag flag)
Definition lib_query.cc:431
LibraryForeachIDFlag
@ IDWALK_RECURSE
@ IDWALK_READONLY
@ IDWALK_DO_INTERNAL_RUNTIME_POINTERS
void BKE_libblock_relink_multiple(Main *bmain, const blender::Span< ID * > ids, eIDRemapType remap_type, blender::bke::id::IDRemapper &id_remapper, int remap_flags)
Definition lib_remap.cc:792
@ ID_REMAP_TYPE_REMAP
@ LIBRARY_IS_ASSET_EDIT_FILE
@ LIBRARY_ASSET_EDITABLE
@ LIBRARY_TAG_RESYNC_REQUIRED
#define FOREACH_MAIN_ID_END
Definition BKE_main.hh:583
#define FOREACH_MAIN_LISTBASE_ID_END
Definition BKE_main.hh:552
#define FOREACH_MAIN_LISTBASE_ID_BEGIN(_lb, _id)
Definition BKE_main.hh:546
#define FOREACH_MAIN_LISTBASE_END
Definition BKE_main.hh:564
#define FOREACH_MAIN_LISTBASE_BEGIN(_bmain, _lb)
Definition BKE_main.hh:557
void BKE_main_relations_create(Main *bmain, short flag)
Definition main.cc:551
#define FOREACH_MAIN_ID_BEGIN(_bmain, _id)
Definition BKE_main.hh:577
const char * BKE_main_blendfile_path(const Main *bmain) ATTR_NONNULL()
Definition main.cc:887
void BKE_main_relations_free(Main *bmain)
Definition main.cc:588
void BKE_main_ensure_invariants(Main &bmain, std::optional< blender::Span< ID * > > modified_ids=std::nullopt)
void BKE_main_namemap_destroy(UniqueName_Map **r_name_map) ATTR_NONNULL()
bool BKE_main_namemap_contain_name(Main &bmain, Library *lib, short id_type, blender::StringRef name)
PackedFile * BKE_packedfile_duplicate(const PackedFile *pf_src)
void BKE_packedfile_free(PackedFile *pf)
void BKE_packedfile_blend_write(BlendWriter *writer, const PackedFile *pf)
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:731
#define LISTBASE_FOREACH(type, var, list)
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1
bool BLI_path_is_rel(const char *path) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:693
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
#define UNUSED_VARS_NDEBUG(...)
#define BLO_write_id_struct(writer, struct_name, id_address, id)
bool BLO_write_is_undo(BlendWriter *writer)
#define BLT_I18NCONTEXT_ID_LIBRARY
#define CLOG_ERROR(clg_ref,...)
Definition CLG_log.h:188
#define CLOG_DEBUG(clg_ref,...)
Definition CLG_log.h:191
ID and Library types, which are fundamental for SDNA.
#define ID_IS_PACKED(_id)
Definition DNA_ID.h:700
#define ID_IS_LINKED(_id)
Definition DNA_ID.h:694
@ INDEX_ID_LI
Definition DNA_ID.h:1281
#define FILTER_ID_LI
Definition DNA_ID.h:1235
@ LIBRARY_FLAG_IS_ARCHIVE
Definition DNA_ID.h:593
@ ID_LI
@ ID_KE
@ ID_SCE
Object groups, one object can be in many groups at once.
BMesh const char void * data
const Value & lookup(const Key &key) const
Definition BLI_map.hh:545
bool add(const Key &key, const Value &value)
Definition BLI_map.hh:295
Value lookup_default(const Key &key, const Value &default_value) const
Definition BLI_map.hh:570
bool contains(const Key &key) const
Definition BLI_set.hh:310
bool add(const Key &key)
Definition BLI_set.hh:248
bool add(const Key &key)
Span< Key > as_span() const
int64_t size() const
void append(const T &value)
const T & last(const int64_t n=0) const
void add(ID *old_id, ID *new_id)
#define GS(x)
void BKE_library_filepath_set(Main *bmain, Library *lib, const char *filepath)
Definition library.cc:229
void BKE_library_main_rebuild_hierarchy(Main *bmain)
Definition library.cc:328
static void library_runtime_reset(Library *lib)
Definition library.cc:55
static void rebuild_hierarchy_best_parent_find(Main *bmain, blender::Set< Library * > &directly_used_libs, Library *lib)
Definition library.cc:254
static void library_blend_read_data(BlendDataReader *, ID *id)
Definition library.cc:183
static void pack_linked_ids(Main &bmain, const blender::Set< ID * > &ids_to_pack)
Definition library.cc:601
static void library_blend_read_after_liblink(BlendLibReader *, ID *id)
Definition library.cc:189
static void library_foreach_path(ID *id, BPathForeachPathData *bpath_data)
Definition library.cc:146
static void library_blend_write_data(BlendWriter *writer, ID *id, const void *id_address)
Definition library.cc:163
static void library_foreach_id(ID *id, LibraryForeachIDData *data)
Definition library.cc:110
static Library * add_archive_library(Main &bmain, Library &reference_library)
Definition library.cc:436
static void library_init_data(ID *id)
Definition library.cc:60
static void library_copy_data(Main *bmain, std::optional< Library * > owner_library, ID *id_dst, const ID *id_src, int)
Definition library.cc:76
static void library_free_data(ID *id)
Definition library.cc:66
static void pack_linked_id(Main &bmain, ID *linked_id, const id_hash::ValidDeepHashes &deep_hashes, blender::Map< IDHash, ID * > &already_packed_ids, blender::VectorSet< ID * > &ids_to_remap, blender::bke::id::IDRemapper &id_remapper)
Definition library.cc:506
#define LOG(level)
Definition log.h:97
std::variant< ValidDeepHashes, DeepHashErrors > IDHashResult
IDHashResult compute_linked_id_deep_hashes(const Main &bmain, Span< const ID * > root_ids)
Definition id_hash.cc:233
Library * ensure_archive_library(Main &bmain, ID &id, Library &reference_library, const IDHash &id_deep_hash, bool &is_new)
Definition library.cc:468
void main_cleanup_parent_archives(Main &bmain)
Definition library.cc:714
void pack_linked_id_hierarchy(Main &bmain, ID &root_id)
Definition library.cc:658
Library * search_filepath_abs(ListBase *libraries, blender::StringRef filepath_abs)
Definition library.cc:417
const char * name
Definition DNA_ID.h:414
struct Library * lib
Definition DNA_ID.h:420
char name[258]
Definition DNA_ID.h:432
struct ID * newid
Definition DNA_ID.h:418
IDHash deep_hash
Definition DNA_ID.h:474
LibraryForeachIDCallbackFlag cb_flag
struct PackedFile * packedfile
Definition DNA_ID.h:572
char filepath[1024]
Definition DNA_ID.h:552
ID id
Definition DNA_ID.h:550
uint16_t flag
Definition DNA_ID.h:555
LibraryRuntimeHandle * runtime
Definition DNA_ID.h:579
struct Library * archive_parent_library
Definition DNA_ID.h:563
MainIDRelationsEntryItem * next
Definition BKE_main.hh:58
MainIDRelationsEntryItem * from_ids
Definition BKE_main.hh:75
GHash * relations_from_pointers
Definition BKE_main.hh:130
short subversionfile
Definition BKE_main.hh:182
ListBase libraries
Definition BKE_main.hh:279
short versionfile
Definition BKE_main.hh:181
MainIDRelations * relations
Definition BKE_main.hh:329
Map< const ID *, IDHash > hashes
#define N_(msgid)
static DynamicLibrary lib