Blender V5.0
readfile.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
8
9#include "fmt/core.h"
10
11#include <cerrno>
12#include <cstdarg> /* for va_start/end. */
13#include <cstddef> /* for offsetof. */
14#include <cstdlib> /* for atoi. */
15#include <cstring>
16#include <ctime> /* for gmtime. */
17#include <fcntl.h> /* for open flags (O_BINARY, O_RDONLY). */
18#include <queue>
19
20#ifndef WIN32
21# include <unistd.h> /* for read close */
22#else
23# include "BLI_winstuff.h"
24# include "winsock2.h"
25# include <io.h> /* for open close read */
26#endif
27
28#include <fmt/format.h>
29
30#include "CLG_log.h"
31
32/* allow readfile to use deprecated functionality */
33#define DNA_DEPRECATED_ALLOW
34
35#include "DNA_asset_types.h"
39#include "DNA_genfile.h"
40#include "DNA_key_types.h"
41#include "DNA_layer_types.h"
42#include "DNA_node_types.h"
44#include "DNA_screen_types.h"
45#include "DNA_sdna_types.h"
46#include "DNA_userdef_types.h"
48
50#include "MEM_guardedalloc.h"
51
52#include "BLI_endian_defines.h"
53#include "BLI_fileops.h"
54#include "BLI_ghash.h"
55#include "BLI_map.hh"
56#include "BLI_memarena.h"
57#include "BLI_set.hh"
58#include "BLI_string.h"
59#include "BLI_string_ref.hh"
60#include "BLI_string_utf8.h"
61#include "BLI_string_utils.hh"
62#include "BLI_threads.h"
63#include "BLI_time.h"
64#include "BLI_utildefines.h"
65
66#include "BLT_translation.hh"
67
68#include "BKE_anim_data.hh"
69#include "BKE_animsys.h"
70#include "BKE_asset.hh"
71#include "BKE_blender_version.h"
72#include "BKE_collection.hh"
73#include "BKE_global.hh" /* for G */
74#include "BKE_idprop.hh"
75#include "BKE_idtype.hh"
76#include "BKE_layer.hh"
77#include "BKE_lib_id.hh"
78#include "BKE_lib_override.hh"
79#include "BKE_lib_query.hh"
80#include "BKE_lib_remap.hh"
81#include "BKE_library.hh"
82#include "BKE_main.hh" /* for Main */
83#include "BKE_main_idmap.hh"
85#include "BKE_main_namemap.hh"
86#include "BKE_material.hh"
87#include "BKE_mesh.hh"
88#include "BKE_modifier.hh"
89#include "BKE_nla.hh"
90#include "BKE_node.hh" /* for tree type defines */
92#include "BKE_object.hh"
93#include "BKE_packedFile.hh"
94#include "BKE_preferences.h"
95#include "BKE_report.hh"
96#include "BKE_scene.hh"
97#include "BKE_screen.hh"
98#include "BKE_undo_system.hh"
99#include "BKE_workspace.hh"
100
101#include "DRW_engine.hh"
102
103#include "DEG_depsgraph.hh"
104
105#include "BLO_blend_validate.hh"
106#include "BLO_read_write.hh"
107#include "BLO_readfile.hh"
108#include "BLO_undofile.hh"
109
110#include "SEQ_iterator.hh"
111#include "SEQ_modifier.hh"
112#include "SEQ_sequencer.hh"
113#include "SEQ_utils.hh"
114
115#include "IMB_colormanagement.hh"
116
117#include "readfile.hh"
118#include "versioning_common.hh"
119
120/* Make preferences read-only. */
121#define U (*((const UserDef *)&U))
122
172
180#define USE_BHEAD_READ_ON_DEMAND
181
182static CLG_LogRef LOG = {"blend.readfile"};
183static CLG_LogRef LOG_UNDO = {"undo"};
184
185#if ENDIAN_ORDER == B_ENDIAN
186# warning "Support for Big Endian endianness is deprecated and will be removed in Blender 5.0"
187#endif
188
189/* local prototypes */
190static void read_libraries(FileData *basefd);
191static void *read_struct(FileData *fd, BHead *bh, const char *blockname, const int id_type_index);
192static BHead *find_bhead_from_code_name(FileData *fd, const short idcode, const char *name);
193
194struct BHeadN {
196#ifdef USE_BHEAD_READ_ON_DEMAND
198 off64_t file_offset;
201#endif
204};
205
206#define BHEADN_FROM_BHEAD(bh) ((BHeadN *)POINTER_OFFSET(bh, -int(offsetof(BHeadN, bhead))))
207
212#define BHEAD_USE_READ_ON_DEMAND(bhead) ((bhead)->code == BLO_CODE_DATA)
213
214/* -------------------------------------------------------------------- */
217
219 const eReportType type,
220 const char *format,
221 ...)
222{
223 char fixed_buf[1024]; /* should be long enough */
224
225 va_list args;
226
227 va_start(args, format);
228 vsnprintf(fixed_buf, sizeof(fixed_buf), format, args);
229 va_end(args);
230
231 fixed_buf[sizeof(fixed_buf) - 1] = '\0';
232
233 BKE_report(reports->reports, type, fixed_buf);
234
235 if (G.background == 0) {
236 BKE_report_log(type, fixed_buf, &LOG);
237 }
238}
239
240/* for reporting linking messages */
242{
243 return lib->runtime->parent ? lib->runtime->parent->runtime->filepath_abs : "<direct>";
244}
245
247
248/* -------------------------------------------------------------------- */
251
253 void *newp;
254
256 int nr;
257};
258
262
264{
265 return MEM_new<OldNewMap>(__func__);
266}
267
272static bool oldnewmap_insert(OldNewMap *onm, const void *oldaddr, void *newaddr, const int nr)
273{
274 if (oldaddr == nullptr || newaddr == nullptr) {
275 return false;
276 }
277
278 return onm->map.add_overwrite(oldaddr, NewAddress{newaddr, nr});
279}
280
281static void oldnewmap_lib_insert(FileData *fd, const void *oldaddr, ID *newaddr, const int id_code)
282{
283 oldnewmap_insert(fd->libmap, oldaddr, newaddr, id_code);
284}
285
287 const void *oldaddr,
288 void *newaddr,
289 const int nr)
290{
291 oldnewmap_insert(onm, oldaddr, newaddr, nr);
292}
293
294static void *oldnewmap_lookup_and_inc(OldNewMap *onm, const void *addr, const bool increase_users)
295{
296 NewAddress *entry = onm->map.lookup_ptr(addr);
297 if (entry == nullptr) {
298 return nullptr;
299 }
300 if (increase_users) {
301 entry->nr++;
302 }
303 return entry->newp;
304}
305
306/* for libdata, NewAddress.nr has ID code, no increment */
307static void *oldnewmap_liblookup(OldNewMap *onm, const void *addr, const bool is_linked_only)
308{
309 if (addr == nullptr) {
310 return nullptr;
311 }
312
313 ID *id = static_cast<ID *>(oldnewmap_lookup_and_inc(onm, addr, false));
314 if (id == nullptr) {
315 return nullptr;
316 }
317 if (!is_linked_only || ID_IS_LINKED(id)) {
318 return id;
319 }
320 return nullptr;
321}
322
323static void oldnewmap_clear(OldNewMap *onm)
324{
325 /* Free unused data. */
326 for (NewAddress &new_addr : onm->map.values()) {
327 if (new_addr.nr == 0) {
328 MEM_freeN(new_addr.newp);
329 }
330 }
331 onm->map.clear();
332}
333
334static void oldnewmap_free(OldNewMap *onm)
335{
336 MEM_delete(onm);
337}
338
340
341/* -------------------------------------------------------------------- */
344
345static void add_main_to_main(Main *mainvar, Main *from)
346{
347 if (from->is_read_invalid) {
348 mainvar->is_read_invalid = true;
349 }
350
351 MainListsArray lbarray = BKE_main_lists_get(*mainvar);
352 MainListsArray fromarray = BKE_main_lists_get(*from);
353 int a = fromarray.size();
354 while (a--) {
355 BLI_movelisttolist(lbarray[a], fromarray[a]);
356 }
357}
358
359void blo_join_main(Main *bmain)
360{
361 BLI_assert(bmain->split_mains);
362 /* For now, we could relax this requirement in the future if needed. */
363 BLI_assert((*bmain->split_mains)[0] == bmain);
364
365 if (bmain->split_mains->size() == 1) {
366 bmain->split_mains.reset();
367 return;
368 }
369
370 if (bmain->id_map != nullptr) {
371 /* Cannot keep this since we add some IDs from joined mains. */
373 bmain->id_map = nullptr;
374 }
375 /* Will no longer be valid after joining. */
377
378 for (Main *tojoin : *bmain->split_mains) {
379 if (tojoin == bmain) {
380 continue;
381 }
382 BLI_assert(((tojoin->curlib->runtime->tag & LIBRARY_IS_ASSET_EDIT_FILE) != 0) ==
383 tojoin->is_asset_edit_file);
384 add_main_to_main(bmain, tojoin);
385 tojoin->split_mains.reset();
386 BKE_main_free(tojoin);
387 }
388
389 BLI_assert(bmain->split_mains.use_count() == 1);
390 bmain->split_mains.reset();
391}
392
393static void split_libdata(ListBase *lb_src,
394 blender::Vector<Main *> &lib_main_array,
395 const bool do_split_packed_ids)
396{
397 for (ID *id = static_cast<ID *>(lb_src->first), *idnext; id; id = idnext) {
398 idnext = static_cast<ID *>(id->next);
399
400 if (id->lib && (do_split_packed_ids || (id->lib->flag & LIBRARY_FLAG_IS_ARCHIVE) == 0)) {
401 if (uint(id->lib->runtime->temp_index) < lib_main_array.size()) {
402 Main *mainvar = lib_main_array[id->lib->runtime->temp_index];
403 BLI_assert(mainvar->curlib == id->lib);
404 ListBase *lb_dst = which_libbase(mainvar, GS(id->name));
405 BLI_remlink(lb_src, id);
406 BLI_addtail(lb_dst, id);
407 }
408 else {
409 CLOG_ERROR(&LOG, "Invalid library for '%s'", id->name);
410 }
411 }
412 }
413}
414
415void blo_split_main(Main *bmain, const bool do_split_packed_ids)
416{
417 BLI_assert(!bmain->split_mains);
418 bmain->split_mains = std::make_shared<blender::VectorSet<Main *>>();
419 bmain->split_mains->add_new(bmain);
420
421 if (BLI_listbase_is_empty(&bmain->libraries)) {
422 return;
423 }
424
425 if (bmain->id_map != nullptr) {
426 /* Cannot keep this since we remove some IDs from given main. */
428 bmain->id_map = nullptr;
429 }
430
431 /* Will no longer be valid after splitting. */
433
434 /* (Library.temp_index -> Main), lookup table */
435 blender::Vector<Main *> lib_main_array;
436
437 int i = 0;
438 int lib_index = 0;
439 for (Library *lib = static_cast<Library *>(bmain->libraries.first); lib;
440 lib = static_cast<Library *>(lib->id.next), i++)
441 {
442 if (!do_split_packed_ids && (lib->flag & LIBRARY_FLAG_IS_ARCHIVE) != 0) {
443 continue;
444 }
445 Main *libmain = BKE_main_new();
446 libmain->curlib = lib;
447 libmain->versionfile = lib->runtime->versionfile;
448 libmain->subversionfile = lib->runtime->subversionfile;
451 libmain->is_asset_edit_file = (lib->runtime->tag & LIBRARY_IS_ASSET_EDIT_FILE) != 0;
452 libmain->colorspace = lib->runtime->colorspace;
453 bmain->split_mains->add_new(libmain);
454 libmain->split_mains = bmain->split_mains;
455 lib->runtime->temp_index = lib_index;
456 lib_main_array.append(libmain);
457 lib_index++;
458 }
459
460 MainListsArray lbarray = BKE_main_lists_get(*bmain);
461 i = lbarray.size();
462 while (i--) {
463 ID *id = static_cast<ID *>(lbarray[i]->first);
464 if (id == nullptr || GS(id->name) == ID_LI) {
465 /* No ID_LI data-block should ever be linked anyway, but just in case, better be explicit. */
466 continue;
467 }
468 split_libdata(lbarray[i], lib_main_array, do_split_packed_ids);
469 }
470}
471
473{
474 BHead *bhead;
475
476 for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
477 if (bhead->code == BLO_CODE_GLOB) {
478 FileGlobal *fg = static_cast<FileGlobal *>(
479 read_struct(fd, bhead, "Data from Global block", INDEX_ID_NULL));
480 if (fg) {
481 if (main->versionfile != fd->fileversion) {
482 /* `versionfile` remains unset when linking from a new library (`main` has then just be
483 * created by `blo_find_main`). */
484 BLI_assert(main->versionfile == 0);
485 main->versionfile = short(fd->fileversion);
486 }
487 main->subversionfile = fg->subversion;
488 main->minversionfile = fg->minversion;
489 main->minsubversionfile = fg->minsubversion;
490 main->has_forward_compatibility_issues = !MAIN_VERSION_FILE_OLDER_OR_EQUAL(
492 main->is_asset_edit_file = (fg->fileflags & G_FILE_ASSET_EDIT_FILE) != 0;
493 STRNCPY(main->colorspace.scene_linear_name, fg->colorspace_scene_linear_name);
494 main->colorspace.scene_linear_to_xyz = blender::float3x3(
496 MEM_freeN(fg);
497 }
498 else if (bhead->code == BLO_CODE_ENDB) {
499 break;
500 }
501 }
502 }
503 if (main->curlib) {
504 main->curlib->runtime->versionfile = main->versionfile;
505 main->curlib->runtime->subversionfile = main->subversionfile;
507 main->curlib->runtime->tag, main->is_asset_edit_file, LIBRARY_IS_ASSET_EDIT_FILE);
508 main->curlib->runtime->colorspace = main->colorspace;
509 }
510}
511
512static bool blo_bhead_is_id(const BHead *bhead)
513{
514 /* BHead codes are four bytes (like 'ENDB', 'TEST', etc.), but if the two most-significant bytes
515 * are zero, the values actually indicate an ID type. */
516 return bhead->code <= 0xFFFF;
517}
518
519static bool blo_bhead_is_id_valid_type(const BHead *bhead)
520{
521 if (!blo_bhead_is_id(bhead)) {
522 return false;
523 }
524
525 const short id_type_code = bhead->code & 0xFFFF;
526 return BKE_idtype_idcode_is_valid(id_type_code);
527}
528
530{
531 /* dummy values */
532 bool is_link = false;
533 int code_prev = BLO_CODE_ENDB;
534
535 fd->bhead_idname_map.emplace();
536 for (BHead *bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
537 if (code_prev != bhead->code) {
538 code_prev = bhead->code;
539 is_link = blo_bhead_is_id_valid_type(bhead) ?
540 BKE_idtype_idcode_is_linkable(short(code_prev)) :
541 false;
542 }
543
544 if (is_link) {
545 /* #idname may be null in case the ID name of the given BHead is detected as invalid (e.g.
546 * because it comes from a future version of Blender allowing for longer ID names). These
547 * 'invalid-named IDs' are skipped here, which will e.g. prevent them from being linked. */
548 const char *idname = blo_bhead_id_name(fd, bhead);
549 if (idname) {
550 fd->bhead_idname_map->add(idname, bhead);
551 }
552 }
553 }
554}
555
556void blo_readfile_invalidate(FileData *fd, Main *bmain, const char *message)
557{
558 /* Tag given `bmain`, and 'root 'local' main one (in case given one is a library one) as invalid.
559 */
560 bmain->is_read_invalid = true;
561 if (bmain->split_mains) {
562 (*bmain->split_mains)[0]->is_read_invalid = true;
563 }
564
566 RPT_ERROR,
567 "A critical error happened (the blend file is likely corrupted): %s",
568 message);
569}
570
572
573/* -------------------------------------------------------------------- */
576
586
591
593{
594 BHeadN *new_bhead = nullptr;
595
596 if (fd) {
597 if (!fd->is_eof) {
598 std::optional<BHead> bhead_opt = BLO_readfile_read_bhead(fd->file,
600 BHead *bhead = nullptr;
601 if (!bhead_opt.has_value()) {
602 fd->is_eof = true;
603 }
604 else if (bhead_opt->len < 0) {
605 /* Make sure people are not trying to parse bad blend files. */
606 fd->is_eof = true;
607 }
608 else {
609 bhead = &bhead_opt.value();
610 }
611
612 /* bhead now contains the (converted) bhead structure. Now read
613 * the associated data and put everything in a BHeadN (creative naming !)
614 */
615 if (fd->is_eof) {
616 /* pass */
617 }
618#ifdef USE_BHEAD_READ_ON_DEMAND
619 else if (fd->file->seek != nullptr && BHEAD_USE_READ_ON_DEMAND(bhead)) {
620 /* Delay reading bhead content. */
621 new_bhead = MEM_mallocN<BHeadN>("new_bhead");
622 if (new_bhead) {
623 new_bhead->next = new_bhead->prev = nullptr;
624 new_bhead->file_offset = fd->file->offset;
625 new_bhead->has_data = false;
626 new_bhead->is_memchunk_identical = false;
627 new_bhead->bhead = *bhead;
628 const off64_t seek_new = fd->file->seek(fd->file, bhead->len, SEEK_CUR);
629 if (UNLIKELY(seek_new == -1)) {
630 fd->is_eof = true;
631 MEM_freeN(new_bhead);
632 new_bhead = nullptr;
633 }
634 else {
635 BLI_assert(fd->file->offset == seek_new);
636 }
637 }
638 else {
639 fd->is_eof = true;
640 }
641 }
642#endif
643 else {
644 new_bhead = static_cast<BHeadN *>(
645 MEM_mallocN(sizeof(BHeadN) + size_t(bhead->len), "new_bhead"));
646 if (new_bhead) {
647 new_bhead->next = new_bhead->prev = nullptr;
648#ifdef USE_BHEAD_READ_ON_DEMAND
649 new_bhead->file_offset = 0; /* don't seek. */
650 new_bhead->has_data = true;
651#endif
652 new_bhead->is_memchunk_identical = false;
653 new_bhead->bhead = *bhead;
654
655 const int64_t readsize = fd->file->read(fd->file, new_bhead + 1, size_t(bhead->len));
656
657 if (UNLIKELY(readsize != bhead->len)) {
658 fd->is_eof = true;
659 MEM_freeN(new_bhead);
660 new_bhead = nullptr;
661 }
662 else {
663 if (fd->flags & FD_FLAGS_IS_MEMFILE) {
664 new_bhead->is_memchunk_identical = ((UndoReader *)fd->file)->memchunk_identical;
665 }
666 }
667 }
668 else {
669 fd->is_eof = true;
670 }
671 }
672 }
673 }
674
675 /* We've read a new block. Now add it to the list
676 * of blocks.
677 */
678 if (new_bhead) {
679 BLI_addtail(&fd->bhead_list, new_bhead);
680 }
681
682 return new_bhead;
683}
684
686{
687 BHeadN *new_bhead;
688 BHead *bhead = nullptr;
689
690 /* Rewind the file
691 * Read in a new block if necessary
692 */
693 new_bhead = static_cast<BHeadN *>(fd->bhead_list.first);
694 if (new_bhead == nullptr) {
695 new_bhead = get_bhead(fd);
696 }
697
698 if (new_bhead) {
699 bhead = &new_bhead->bhead;
700 }
701
702 return bhead;
703}
704
705BHead *blo_bhead_prev(FileData * /*fd*/, BHead *thisblock)
706{
707 BHeadN *bheadn = BHEADN_FROM_BHEAD(thisblock);
708 BHeadN *prev = bheadn->prev;
709
710 return (prev) ? &prev->bhead : nullptr;
711}
712
714{
715 BHeadN *new_bhead = nullptr;
716 BHead *bhead = nullptr;
717
718 if (thisblock) {
719 /* bhead is actually a sub part of BHeadN
720 * We calculate the BHeadN pointer from the BHead pointer below */
721 new_bhead = BHEADN_FROM_BHEAD(thisblock);
722
723 /* get the next BHeadN. If it doesn't exist we read in the next one */
724 new_bhead = new_bhead->next;
725 if (new_bhead == nullptr) {
726 new_bhead = get_bhead(fd);
727 }
728 }
729
730 if (new_bhead) {
731 /* here we do the reverse:
732 * go from the BHeadN pointer to the BHead pointer */
733 bhead = &new_bhead->bhead;
734 }
735
736 return bhead;
737}
738
739#ifdef USE_BHEAD_READ_ON_DEMAND
740static bool blo_bhead_read_data(FileData *fd, BHead *thisblock, void *buf)
741{
742 bool success = true;
743 BHeadN *new_bhead = BHEADN_FROM_BHEAD(thisblock);
744 BLI_assert(new_bhead->has_data == false && new_bhead->file_offset != 0);
745 off64_t offset_backup = fd->file->offset;
746 if (UNLIKELY(fd->file->seek(fd->file, new_bhead->file_offset, SEEK_SET) == -1)) {
747 success = false;
748 }
749 else {
750 if (UNLIKELY(fd->file->read(fd->file, buf, size_t(new_bhead->bhead.len)) !=
751 new_bhead->bhead.len))
752 {
753 success = false;
754 }
755 else {
756 if (fd->flags & FD_FLAGS_IS_MEMFILE) {
757 new_bhead->is_memchunk_identical = ((UndoReader *)fd->file)->memchunk_identical;
758 }
759 }
760 }
761 if (fd->file->seek(fd->file, offset_backup, SEEK_SET) == -1) {
762 success = false;
763 }
764 return success;
765}
766
767static BHead *blo_bhead_read_full(FileData *fd, BHead *thisblock)
768{
769 BHeadN *new_bhead = BHEADN_FROM_BHEAD(thisblock);
770 BHeadN *new_bhead_data = static_cast<BHeadN *>(
771 MEM_mallocN(sizeof(BHeadN) + new_bhead->bhead.len, "new_bhead"));
772 new_bhead_data->bhead = new_bhead->bhead;
773 new_bhead_data->file_offset = new_bhead->file_offset;
774 new_bhead_data->has_data = true;
775 new_bhead_data->is_memchunk_identical = false;
776 if (!blo_bhead_read_data(fd, thisblock, new_bhead_data + 1)) {
777 MEM_freeN(new_bhead_data);
778 return nullptr;
779 }
780 return &new_bhead_data->bhead;
781}
782#endif /* USE_BHEAD_READ_ON_DEMAND */
783
784const char *blo_bhead_id_name(FileData *fd, const BHead *bhead)
785{
787 const char *id_name = reinterpret_cast<const char *>(
788 POINTER_OFFSET(bhead, sizeof(*bhead) + fd->id_name_offset));
789 if (std::memchr(id_name, '\0', MAX_ID_NAME)) {
790 return id_name;
791 }
792
793 /* ID name longer than MAX_ID_NAME - 1, or otherwise corrupted. */
795 return nullptr;
796}
797
798short blo_bhead_id_flag(const FileData *fd, const BHead *bhead)
799{
801 if (fd->id_flag_offset < 0) {
802 return 0;
803 }
804 return *reinterpret_cast<const short *>(
805 POINTER_OFFSET(bhead, sizeof(*bhead) + fd->id_flag_offset));
806}
807
809{
811 return (fd->id_asset_data_offset >= 0) ?
812 *(AssetMetaData **)POINTER_OFFSET(bhead, sizeof(*bhead) + fd->id_asset_data_offset) :
813 nullptr;
814}
815
816static const IDHash *blo_bhead_id_deep_hash(const FileData *fd, const BHead *bhead)
817{
819 if (fd->id_flag_offset < 0 || fd->id_deep_hash_offset < 0) {
820 return nullptr;
821 }
822 const short flag = blo_bhead_id_flag(fd, bhead);
824 return nullptr;
825 }
826 return reinterpret_cast<const IDHash *>(
827 POINTER_OFFSET(bhead, sizeof(*bhead) + fd->id_deep_hash_offset));
828}
829
831{
833 if (std::holds_alternative<BlenderHeaderInvalid>(header_variant)) {
834 return;
835 }
836 if (std::holds_alternative<BlenderHeaderUnknown>(header_variant)) {
838 return;
839 }
840 const BlenderHeader &header = std::get<BlenderHeader>(header_variant);
841 fd->flags |= FD_FLAGS_FILE_OK;
842 if (header.pointer_size == 4) {
844 }
845 if (header.pointer_size != sizeof(void *)) {
847 }
848 if (header.endian != ENDIAN_ORDER) {
850 }
851 fd->fileversion = header.file_version;
852 fd->blender_header = header;
853}
854
858static bool read_file_dna(FileData *fd, const char **r_error_message)
859{
860 BHead *bhead;
861 int subversion = 0;
862
863 for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
864 if (bhead->code == BLO_CODE_GLOB) {
865 /* Before this, the subversion didn't exist in 'FileGlobal' so the subversion
866 * value isn't accessible for the purpose of DNA versioning in this case. */
867 if (fd->fileversion <= 242) {
868 continue;
869 }
870 /* We can't use read_global because this needs 'DNA1' to be decoded,
871 * however the first 4 chars are _always_ the subversion. */
872 const FileGlobal *fg = reinterpret_cast<const FileGlobal *>(&bhead[1]);
873 BLI_STATIC_ASSERT(offsetof(FileGlobal, subvstr) == 0, "Must be first: subvstr")
874 char num[5];
875 memcpy(num, fg->subvstr, 4);
876 num[4] = 0;
877 subversion = atoi(num);
878 }
879 else if (bhead->code == BLO_CODE_DNA1) {
881 const bool do_alias = false; /* Postpone until after #blo_do_versions_dna runs. */
882 fd->filesdna = DNA_sdna_from_data(&bhead[1], bhead->len, true, do_alias, r_error_message);
883 if (fd->filesdna) {
884 blo_do_versions_dna(fd->filesdna, fd->fileversion, subversion);
885 /* Allow aliased lookups (must be after version patching DNA). */
887
890 fd->filesdna, fd->memsdna, fd->compflags);
891 /* used to retrieve ID names from (bhead+1) */
893 fd->filesdna, "ID", "char", "name[]");
894 BLI_assert(fd->id_name_offset != -1);
896 fd->filesdna, "ID", "AssetMetaData", "*asset_data");
898 fd->filesdna, "ID", "short", "flag");
900 fd->filesdna, "ID", "IDHash", "deep_hash");
901
902 fd->filesubversion = subversion;
903
904 return true;
905 }
906
907 return false;
908 }
909 else if (bhead->code == BLO_CODE_ENDB) {
910 break;
911 }
912 }
913
914 *r_error_message = "Missing DNA block";
915 return false;
916}
917
919{
920 BHead *bhead;
921 int *blend_thumb = nullptr;
922
923 for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
924 if (bhead->code == BLO_CODE_TEST) {
926 int *data = (int *)(bhead + 1);
927
928 if (bhead->len < sizeof(int[2])) {
929 break;
930 }
931
932 const int width = data[0];
933 const int height = data[1];
934 if (!BLEN_THUMB_MEMSIZE_IS_VALID(width, height)) {
935 break;
936 }
937 if (bhead->len < BLEN_THUMB_MEMSIZE_FILE(width, height)) {
938 break;
939 }
940
941 blend_thumb = data;
942 break;
943 }
944 if (bhead->code != BLO_CODE_REND) {
945 /* Thumbnail is stored in TEST immediately after first REND... */
946 break;
947 }
948 }
949
950 return blend_thumb;
951}
952
965{
966 ListBase *lb_iter;
967 /* Using a set is needed, to avoid renaming names when there is no collision, and deal with IDs
968 * being moved around in their list when renamed. A simple set is enough, since here only local
969 * IDs are processed. */
971 blender::Set<ID *> processed_ids;
972
973 FOREACH_MAIN_LISTBASE_BEGIN (bmain, lb_iter) {
974 LISTBASE_FOREACH_MUTABLE (ID *, id_iter, lb_iter) {
975 if (processed_ids.contains(id_iter)) {
976 continue;
977 }
978 processed_ids.add_new(id_iter);
979 /* Linked IDs can be fully ignored here, 'long names' IDs cannot be linked in any way. */
980 if (ID_IS_LINKED(id_iter)) {
981 continue;
982 }
983 if (!used_names.contains(id_iter->name)) {
984 used_names.add_new(id_iter->name);
985 continue;
986 }
987
989 *bmain, *lb_iter, *id_iter, nullptr, IDNewNameMode::RenameExistingNever, false);
990 BLI_assert(!used_names.contains(id_iter->name));
991 used_names.add_new(id_iter->name);
992 CLOG_DEBUG(&LOG, "ID name has been de-duplicated to '%s'", id_iter->name);
993 }
994 }
996}
997
1007{
1008 /* NOTE: A large part of this code follows a similar logic to
1009 * #foreach_action_slot_use_with_references.
1010 *
1011 * However, no slot identifier should ever be skipped here, even if it is not in use in any way,
1012 * since it is critical to remove all non-null terminated strings.
1013 */
1014
1015 ID *id_iter;
1016 FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
1017 switch (GS(id_iter->name)) {
1018 case ID_AC: {
1019 bool has_truncated_slot_identifer = false;
1020 bAction *act = reinterpret_cast<bAction *>(id_iter);
1021 for (int i = 0; i < act->slot_array_num; i++) {
1023 CLOG_DEBUG(&LOG,
1024 "Truncated too long action slot name to '%s'",
1025 act->slot_array[i]->identifier);
1026 has_truncated_slot_identifer = true;
1027 }
1028 }
1029 if (!has_truncated_slot_identifer) {
1030 continue;
1031 }
1032
1033 /* If there are truncated slots identifiers, ensuring their uniqueness must happen in a
1034 * second loop, to avoid e.g. an attempt to read a slot identifier that has not yet been
1035 * truncated. */
1036 for (int i = 0; i < act->slot_array_num; i++) {
1038 [&](const blender::StringRef name) -> bool {
1039 for (int j = 0; j < act->slot_array_num; j++) {
1040 if (i == j) {
1041 continue;
1042 }
1043 if (act->slot_array[j]->identifier == name) {
1044 return true;
1045 }
1046 }
1047 return false;
1048 },
1049 "",
1050 '.',
1051 act->slot_array[i]->identifier,
1052 sizeof(act->slot_array[i]->identifier));
1053 }
1054 break;
1055 }
1056 case ID_OB: {
1057 auto visit_constraint = [](const bConstraint &constraint) -> bool {
1058 if (constraint.type != CONSTRAINT_TYPE_ACTION) {
1059 return true;
1060 }
1061 bActionConstraint *constraint_data = static_cast<bActionConstraint *>(constraint.data);
1063 CLOG_DEBUG(&LOG,
1064 "Truncated too long bActionConstraint.last_slot_identifier to '%s'",
1065 constraint_data->last_slot_identifier);
1066 }
1067 return true;
1068 };
1069
1070 Object *object = reinterpret_cast<Object *>(id_iter);
1071 LISTBASE_FOREACH (bConstraint *, con, &object->constraints) {
1072 visit_constraint(*con);
1073 }
1074 if (object->pose) {
1075 LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
1076 LISTBASE_FOREACH (bConstraint *, con, &pchan->constraints) {
1077 visit_constraint(*con);
1078 }
1079 }
1080 }
1081 }
1083 default: {
1084 AnimData *anim_data = BKE_animdata_from_id(id_iter);
1085 if (anim_data) {
1087 CLOG_DEBUG(&LOG,
1088 "Truncated too long AnimData.last_slot_identifier to '%s'",
1089 anim_data->last_slot_identifier);
1090 }
1092 CLOG_DEBUG(&LOG,
1093 "Truncated too long AnimData.tmp_last_slot_identifier to '%s'",
1094 anim_data->tmp_last_slot_identifier);
1095 }
1096
1097 blender::bke::nla::foreach_strip_adt(*anim_data, [&](NlaStrip *strip) -> bool {
1099 CLOG_DEBUG(&LOG,
1100 "Truncated too long NlaStrip.last_slot_identifier to '%s'",
1101 strip->last_slot_identifier);
1102 }
1103
1104 return true;
1105 });
1106 }
1107 }
1108 }
1110 }
1111}
1112
1114
1115/* -------------------------------------------------------------------- */
1118
1120{
1121 BLI_assert(reports != nullptr);
1122
1123 FileData *fd = MEM_new<FileData>(__func__);
1124
1126
1127 fd->datamap = oldnewmap_new();
1128 fd->globmap = oldnewmap_new();
1129 fd->libmap = oldnewmap_new();
1130 fd->id_by_deep_hash = std::make_shared<blender::Map<IDHash, ID *>>();
1131
1132 fd->reports = reports;
1133
1134 return fd;
1135}
1136
1143{
1144 BLI_assert(fd->filesdna != nullptr);
1145 for (BHead *bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
1146 if (bhead->code != BLO_CODE_GLOB) {
1147 continue;
1148 }
1149
1150 FileGlobal *fg = static_cast<FileGlobal *>(
1151 read_struct(fd, bhead, "Data from Global block", INDEX_ID_NULL));
1152 if ((fg->minversion > BLENDER_FILE_VERSION) ||
1154 {
1155 char writer_ver_str[16];
1156 char min_reader_ver_str[16];
1157 if (fd->fileversion == fg->minversion) {
1159 writer_ver_str, sizeof(writer_ver_str), short(fd->fileversion), fg->subversion);
1161 min_reader_ver_str, sizeof(min_reader_ver_str), fg->minversion, fg->minsubversion);
1162 }
1163 else {
1165 writer_ver_str, sizeof(writer_ver_str), short(fd->fileversion), -1);
1167 min_reader_ver_str, sizeof(min_reader_ver_str), fg->minversion, -1);
1168 }
1169 BKE_reportf(reports,
1170 RPT_ERROR,
1171 "The file was saved by a newer version, open it with Blender %s or later",
1172 min_reader_ver_str);
1173 CLOG_WARN(&LOG,
1174 "%s: File saved by a newer version of Blender (%s), Blender %s or later is "
1175 "needed to open it.",
1176 fd->relabase,
1177 writer_ver_str,
1178 min_reader_ver_str);
1179 MEM_freeN(fg);
1180 return true;
1181 }
1182 MEM_freeN(fg);
1183 return false;
1184 }
1185 return false;
1186}
1187
1189{
1191
1192 if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
1193 BLI_STATIC_ASSERT(ENDIAN_ORDER == L_ENDIAN, "Blender only builds on little endian systems")
1194 BKE_reportf(reports,
1195 RPT_ERROR,
1196 "Blend file '%s' created by a Big Endian version of Blender, support for "
1197 "these files has been removed in Blender 5.0, use an older version of Blender "
1198 "to open and convert it.",
1199 fd->relabase);
1201 fd = nullptr;
1202 }
1203 else if (fd->flags & FD_FLAGS_FILE_OK) {
1204 const char *error_message = nullptr;
1205 if (read_file_dna(fd, &error_message) == false) {
1207 reports, RPT_ERROR, "Failed to read blend file '%s': %s", fd->relabase, error_message);
1209 fd = nullptr;
1210 }
1211 else if (is_minversion_older_than_blender(fd, reports)) {
1213 fd = nullptr;
1214 }
1215 }
1216 else if (fd->flags & FD_FLAGS_FILE_FUTURE) {
1218 reports,
1219 RPT_ERROR,
1220 "Cannot read blend file '%s', incomplete header, may be from a newer version of Blender",
1221 fd->relabase);
1223 fd = nullptr;
1224 }
1225 else {
1226 BKE_reportf(reports, RPT_ERROR, "Failed to read file '%s', not a blend file", fd->relabase);
1228 fd = nullptr;
1229 }
1230
1231 return fd;
1232}
1233
1234static FileData *blo_filedata_from_file_descriptor(const char *filepath,
1235 BlendFileReadReport *reports,
1236 const int filedes)
1237{
1238 char header[7];
1239 FileReader *rawfile = BLI_filereader_new_file(filedes);
1240 FileReader *file = nullptr;
1241
1242 errno = 0;
1243 /* If opening the file failed or we can't read the header, give up. */
1244 if (rawfile == nullptr || rawfile->read(rawfile, header, sizeof(header)) != sizeof(header)) {
1245 BKE_reportf(reports->reports,
1247 "Unable to read '%s': %s",
1248 filepath,
1249 errno ? strerror(errno) : RPT_("insufficient content"));
1250 if (rawfile) {
1251 rawfile->close(rawfile);
1252 }
1253 else {
1254 close(filedes);
1255 }
1256 return nullptr;
1257 }
1258
1259 /* Rewind the file after reading the header. */
1260 rawfile->seek(rawfile, 0, SEEK_SET);
1261
1262 /* Check if we have a regular file. */
1263 if (memcmp(header, "BLENDER", sizeof(header)) == 0) {
1264 /* Try opening the file with memory-mapped IO. */
1265 file = BLI_filereader_new_mmap(filedes);
1266 if (file == nullptr) {
1267 /* `mmap` failed, so just keep using `rawfile`. */
1268 file = rawfile;
1269 rawfile = nullptr;
1270 }
1271 }
1272 else if (BLI_file_magic_is_gzip(header)) {
1273 file = BLI_filereader_new_gzip(rawfile);
1274 if (file != nullptr) {
1275 rawfile = nullptr; /* The `Gzip` #FileReader takes ownership of `rawfile`. */
1276 }
1277 }
1278 else if (BLI_file_magic_is_zstd(header)) {
1279 file = BLI_filereader_new_zstd(rawfile);
1280 if (file != nullptr) {
1281 rawfile = nullptr; /* The `Zstd` #FileReader takes ownership of `rawfile`. */
1282 }
1283 }
1284
1285 /* Clean up `rawfile` if it wasn't taken over. */
1286 if (rawfile != nullptr) {
1287 rawfile->close(rawfile);
1288 }
1289 if (file == nullptr) {
1290 BKE_reportf(reports->reports, RPT_WARNING, "Unrecognized file format '%s'", filepath);
1291 return nullptr;
1292 }
1293
1294 FileData *fd = filedata_new(reports);
1295 fd->file = file;
1296
1297 BLI_stat_t stat;
1298 if (BLI_stat(filepath, &stat) != -1) {
1299 fd->file_stat = stat;
1300 }
1301
1302 return fd;
1303}
1304
1305static FileData *blo_filedata_from_file_open(const char *filepath, BlendFileReadReport *reports)
1306{
1307 errno = 0;
1308 const int file = BLI_open(filepath, O_BINARY | O_RDONLY, 0);
1309 if (file == -1) {
1310 BKE_reportf(reports->reports,
1312 "Unable to open '%s': %s",
1313 filepath,
1314 errno ? strerror(errno) : RPT_("unknown error reading file"));
1315 return nullptr;
1316 }
1317 return blo_filedata_from_file_descriptor(filepath, reports, file);
1318}
1319
1321{
1322 FileData *fd = blo_filedata_from_file_open(filepath, reports);
1323 if (fd != nullptr) {
1324 /* needed for library_append and read_libraries */
1325 STRNCPY(fd->relabase, filepath);
1326
1327 return blo_decode_and_check(fd, reports->reports);
1328 }
1329 return nullptr;
1330}
1331
1336static FileData *blo_filedata_from_file_minimal(const char *filepath)
1337{
1338 BlendFileReadReport read_report{};
1339 FileData *fd = blo_filedata_from_file_open(filepath, &read_report);
1340 if (fd != nullptr) {
1342 if (fd->flags & FD_FLAGS_FILE_OK) {
1343 return fd;
1344 }
1346 }
1347 return nullptr;
1348}
1349
1351 const int memsize,
1352 BlendFileReadReport *reports)
1353{
1354 if (!mem || memsize < MIN_SIZEOFBLENDERHEADER) {
1355 BKE_report(
1356 reports->reports, RPT_WARNING, (mem) ? RPT_("Unable to read") : RPT_("Unable to open"));
1357 return nullptr;
1358 }
1359
1360 FileReader *mem_file = BLI_filereader_new_memory(mem, memsize);
1361 FileReader *file = mem_file;
1362
1363 if (BLI_file_magic_is_gzip(static_cast<const char *>(mem))) {
1364 file = BLI_filereader_new_gzip(mem_file);
1365 }
1366 else if (BLI_file_magic_is_zstd(static_cast<const char *>(mem))) {
1367 file = BLI_filereader_new_zstd(mem_file);
1368 }
1369
1370 if (file == nullptr) {
1371 /* Compression initialization failed. */
1372 mem_file->close(mem_file);
1373 return nullptr;
1374 }
1375
1376 FileData *fd = filedata_new(reports);
1377 fd->file = file;
1378
1379 return blo_decode_and_check(fd, reports->reports);
1380}
1381
1384 BlendFileReadReport *reports)
1385{
1386 if (!memfile) {
1387 BKE_report(reports->reports, RPT_WARNING, "Unable to open blend <memory>");
1388 return nullptr;
1389 }
1390
1391 FileData *fd = filedata_new(reports);
1392 fd->file = BLO_memfile_new_filereader(memfile, params->undo_direction);
1393 fd->undo_direction = params->undo_direction;
1395
1396 return blo_decode_and_check(fd, reports->reports);
1397}
1398
1400{
1401 /* Free all BHeadN data blocks */
1402#ifdef NDEBUG
1404#else
1405 /* Sanity check we're not keeping memory we don't need. */
1406 LISTBASE_FOREACH_MUTABLE (BHeadN *, new_bhead, &fd->bhead_list) {
1407# ifdef USE_BHEAD_READ_ON_DEMAND
1408 if (fd->file->seek != nullptr && BHEAD_USE_READ_ON_DEMAND(&new_bhead->bhead)) {
1409 BLI_assert(new_bhead->has_data == 0);
1410 }
1411# endif
1412 MEM_freeN(new_bhead);
1413 }
1414#endif
1415 fd->file->close(fd->file);
1416
1417 if (fd->filesdna) {
1419 }
1420 if (fd->compflags) {
1421 MEM_freeN(fd->compflags);
1422 }
1423 if (fd->reconstruct_info) {
1425 }
1426
1427 if (fd->datamap) {
1429 }
1430 if (fd->globmap) {
1432 }
1433 if (fd->libmap) {
1435 }
1436 if (fd->old_idmap_uid != nullptr) {
1438 }
1439 if (fd->new_idmap_uid != nullptr) {
1441 }
1443 if (fd->bheadmap) {
1444 MEM_freeN(fd->bheadmap);
1445 }
1446
1447 MEM_delete(fd);
1448}
1449
1451
1452/* -------------------------------------------------------------------- */
1455
1457{
1458 BlendThumbnail *data = nullptr;
1459
1461 if (fd) {
1462 if (const int *fd_data = read_file_thumbnail(fd)) {
1463 const int width = fd_data[0];
1464 const int height = fd_data[1];
1465 if (BLEN_THUMB_MEMSIZE_IS_VALID(width, height)) {
1466 const size_t data_size = BLEN_THUMB_MEMSIZE(width, height);
1467 data = static_cast<BlendThumbnail *>(MEM_mallocN(data_size, __func__));
1468 if (data) {
1469 BLI_assert((data_size - sizeof(*data)) ==
1470 (BLEN_THUMB_MEMSIZE_FILE(width, height) - (sizeof(*fd_data) * 2)));
1471 data->width = width;
1472 data->height = height;
1473 memcpy(data->rect, &fd_data[2], data_size - sizeof(*data));
1474 }
1475 }
1476 }
1478 }
1479
1480 return data;
1481}
1482
1483short BLO_version_from_file(const char *filepath)
1484{
1485 short version = 0;
1487 if (fd) {
1488 version = fd->fileversion;
1490 }
1491 return version;
1492}
1493
1495
1496/* -------------------------------------------------------------------- */
1499
1500/* Only direct data-blocks. */
1501static void *newdataadr(FileData *fd, const void *adr)
1502{
1503 return oldnewmap_lookup_and_inc(fd->datamap, adr, true);
1504}
1505
1506/* Only direct data-blocks. */
1507static void *newdataadr_no_us(FileData *fd, const void *adr)
1508{
1509 return oldnewmap_lookup_and_inc(fd->datamap, adr, false);
1510}
1511
1513{
1514 return oldnewmap_lookup_and_inc(fd->globmap, adr, true);
1515}
1516
1517/* only lib data */
1518static void *newlibadr(FileData *fd, ID * /*self_id*/, const bool is_linked_only, const void *adr)
1519{
1520 return oldnewmap_liblookup(fd->libmap, adr, is_linked_only);
1521}
1522
1524 ID *self_id,
1525 const bool is_linked_only,
1526 const void *adr)
1527{
1528 return newlibadr(fd, self_id, is_linked_only, adr);
1529}
1530
1531/* increases user number */
1533 const void *old,
1534 void *newp)
1535{
1536 for (NewAddress &entry : fd->libmap->map.values()) {
1537 if (old == entry.newp && entry.nr == ID_LINK_PLACEHOLDER) {
1538 entry.newp = newp;
1539 if (newp) {
1540 entry.nr = GS(((ID *)newp)->name);
1541 }
1542 }
1543 }
1544}
1545
1546/* Very rarely needed, allows some form of ID remapping as part of readfile process.
1547 *
1548 * Currently only used to remap duplicate library pointers.
1549 */
1550static void change_ID_pointer_to_real_ID_pointer_fd(FileData *fd, const void *old, void *newp)
1551{
1552 for (NewAddress &entry : fd->libmap->map.values()) {
1553 if (old == entry.newp) {
1554 BLI_assert(BKE_idtype_idcode_is_valid(short(entry.nr)));
1555 entry.newp = newp;
1556 if (newp) {
1557 entry.nr = GS(((ID *)newp)->name);
1558 }
1559 }
1560 }
1561}
1562
1564{
1565 if (bmain->curlib) {
1566 return bmain->curlib->runtime->filedata;
1567 }
1568 else {
1569 return basefd;
1570 }
1571}
1572
1573static void change_link_placeholder_to_real_ID_pointer(FileData *basefd, void *old, void *newp)
1574{
1575 for (Main *mainptr : *basefd->bmain->split_mains) {
1576 FileData *fd = change_ID_link_filedata_get(mainptr, basefd);
1577 if (fd) {
1579 }
1580 }
1581}
1582
1583static void change_ID_pointer_to_real_ID_pointer(FileData *basefd, void *old, void *newp)
1584{
1585 for (Main *mainptr : *basefd->bmain->split_mains) {
1586 FileData *fd = change_ID_link_filedata_get(mainptr, basefd);
1587 if (fd) {
1589 }
1590 }
1591}
1592
1594{
1595 if (fd->old_idmap_uid != nullptr) {
1597 }
1598 fd->old_idmap_uid = BKE_main_idmap_create(bmain, false, nullptr, MAIN_IDMAP_TYPE_UID);
1599}
1600
1605
1610
1613 ID *id, const IDCacheKey *key, void **cache_p, uint /*flags*/, void *cache_storage_v)
1614{
1617
1618 BLOCacheStorage *cache_storage = static_cast<BLOCacheStorage *>(cache_storage_v);
1619 BLI_assert(!BLI_ghash_haskey(cache_storage->cache_map, key));
1620
1621 IDCacheKey *storage_key = static_cast<IDCacheKey *>(
1622 BLI_memarena_alloc(cache_storage->memarena, sizeof(*storage_key)));
1623 *storage_key = *key;
1624 BLOCacheStorageValue *storage_value = static_cast<BLOCacheStorageValue *>(
1625 BLI_memarena_alloc(cache_storage->memarena, sizeof(*storage_value)));
1626 storage_value->cache_v = *cache_p;
1627 storage_value->new_usage_count = 0;
1628 BLI_ghash_insert(cache_storage->cache_map, storage_key, storage_value);
1629}
1630
1633 ID *id, const IDCacheKey *key, void **cache_p, const uint flags, void *cache_storage_v)
1634{
1635 BLOCacheStorage *cache_storage = static_cast<BLOCacheStorage *>(cache_storage_v);
1636
1637 if (cache_storage == nullptr) {
1638 /* In non-undo case, only clear the pointer if it is a purely runtime one.
1639 * If it may be stored in a persistent way in the .blend file, direct_link code is responsible
1640 * to properly deal with it. */
1641 if ((flags & IDTYPE_CACHE_CB_FLAGS_PERSISTENT) == 0) {
1642 *cache_p = nullptr;
1643 }
1644 return;
1645 }
1646
1647 /* Assume that when ID source is tagged as changed, its caches need to be cleared.
1648 * NOTE: This is mainly a work-around for some IDs, like Image, which use a non-depsgraph-handled
1649 * process for part of their updates.
1650 */
1651 if (id->recalc & ID_RECALC_SOURCE) {
1652 *cache_p = nullptr;
1653 return;
1654 }
1655
1656 BLOCacheStorageValue *storage_value = static_cast<BLOCacheStorageValue *>(
1657 BLI_ghash_lookup(cache_storage->cache_map, key));
1658 if (storage_value == nullptr) {
1659 *cache_p = nullptr;
1660 return;
1661 }
1662 storage_value->new_usage_count++;
1663 *cache_p = storage_value->cache_v;
1664}
1665
1668 const IDCacheKey *key,
1669 void **cache_p,
1670 const uint /*flags*/,
1671 void *cache_storage_v)
1672{
1673 BLOCacheStorage *cache_storage = static_cast<BLOCacheStorage *>(cache_storage_v);
1674
1675 BLOCacheStorageValue *storage_value = static_cast<BLOCacheStorageValue *>(
1676 BLI_ghash_lookup(cache_storage->cache_map, key));
1677 if (storage_value == nullptr) {
1678 *cache_p = nullptr;
1679 return;
1680 }
1681 /* If that cache has been restored into some new ID, we want to remove it from old one, otherwise
1682 * keep it there so that it gets properly freed together with its ID. */
1683 if (storage_value->new_usage_count != 0) {
1684 *cache_p = nullptr;
1685 }
1686 else {
1687 BLI_assert(*cache_p == storage_value->cache_v);
1688 }
1689}
1690
1692{
1693 if (fd->flags & FD_FLAGS_IS_MEMFILE) {
1694 BLI_assert(fd->cache_storage == nullptr);
1699
1700 ListBase *lb;
1701 FOREACH_MAIN_LISTBASE_BEGIN (bmain, lb) {
1702 ID *id = static_cast<ID *>(lb->first);
1703 if (id == nullptr) {
1704 continue;
1705 }
1706
1707 const IDTypeInfo *type_info = BKE_idtype_get_info_from_id(id);
1708 if (type_info->foreach_cache == nullptr) {
1709 continue;
1710 }
1711
1713 if (ID_IS_LINKED(id)) {
1714 continue;
1715 }
1717 }
1719 }
1721 }
1722 else {
1723 fd->cache_storage = nullptr;
1724 }
1725}
1726
1728{
1729 if (fd->cache_storage != nullptr) {
1730 ListBase *lb;
1731 FOREACH_MAIN_LISTBASE_BEGIN (bmain_old, lb) {
1732 ID *id = static_cast<ID *>(lb->first);
1733 if (id == nullptr) {
1734 continue;
1735 }
1736
1737 const IDTypeInfo *type_info = BKE_idtype_get_info_from_id(id);
1738 if (type_info->foreach_cache == nullptr) {
1739 continue;
1740 }
1741
1743 if (ID_IS_LINKED(id)) {
1744 continue;
1745 }
1747 }
1749 }
1751 }
1752}
1753
1755{
1756 if (fd->cache_storage != nullptr) {
1757 BLI_ghash_free(fd->cache_storage->cache_map, nullptr, nullptr);
1760 fd->cache_storage = nullptr;
1761 }
1762}
1763
1765
1766/* -------------------------------------------------------------------- */
1769
1776static const char *get_alloc_name(FileData *fd,
1777 BHead *bh,
1778 const char *blockname,
1779 const int id_type_index = INDEX_ID_NULL)
1780{
1781#ifndef NDEBUG
1782 /* Storage key is a pair of (string , int), where the first is the concatenation of the 'owner
1783 * block' string and DNA struct type name, and the second the length of the array, as defined by
1784 * the #BHead.nr value. */
1785 using keyT = const std::pair<const std::string, const int>;
1786#else
1787 /* Storage key is simple int, which is the ID type index. */
1788 using keyT = int;
1789#endif
1790 constexpr std::string_view STORAGE_ID = "readfile";
1791
1792 /* NOTE: This is thread_local storage, so as long as the handling of a same FileData is not
1793 * spread across threads (which is not supported at all currently), this is thread-safe. */
1794 if (!fd->storage_handle) {
1796 std::string(STORAGE_ID));
1797 }
1800 fd->storage_handle);
1801
1802 const bool is_id_data = !blockname && (id_type_index >= 0 && id_type_index < INDEX_ID_MAX);
1803
1804#ifndef NDEBUG
1805 /* Local storage of id type names, for fast access to this info. */
1806 static const std::array<std::string, INDEX_ID_MAX> id_alloc_names = [] {
1807 auto n = decltype(id_alloc_names)();
1808 for (int idtype_index = 0; idtype_index < INDEX_ID_MAX; idtype_index++) {
1809 const IDTypeInfo *idtype_info = BKE_idtype_get_info_from_idtype_index(idtype_index);
1810 BLI_assert(idtype_info);
1811 if (idtype_index == INDEX_ID_NULL) {
1812 /* #INDEX_ID_NULL returns the #IDType_ID_LINK_PLACEHOLDER type info, here we will rather
1813 * use it for unknown/invalid ID types. */
1814 n[size_t(idtype_index)] = "UNKNWOWN";
1815 }
1816 else {
1817 n[size_t(idtype_index)] = idtype_info->name;
1818 }
1819 }
1820 return n;
1821 }();
1822
1823 const std::string block_alloc_name = is_id_data ? id_alloc_names[id_type_index] : blockname;
1824 const std::string struct_name = DNA_struct_identifier(fd->filesdna, bh->SDNAnr);
1825 keyT key{block_alloc_name + struct_name, bh->nr};
1826 if (!storage.contains(key)) {
1827 const std::string alloc_string = fmt::format(
1828 fmt::runtime(is_id_data ? "{}{} (for ID type '{}')" : "{}{} (for block '{}')"),
1829 struct_name,
1830 bh->nr > 1 ? fmt::format("[{}]", bh->nr) : "",
1831 block_alloc_name);
1832 return storage.insert(key, alloc_string);
1833 }
1834 return storage.find(key);
1835#else
1836 /* Simple storage for pure release builds, using integer as key, one entry for each ID type. */
1838 if (is_id_data) {
1839 if (UNLIKELY(!storage.contains(id_type_index))) {
1840 if (id_type_index == INDEX_ID_NULL) {
1841 return storage.insert(id_type_index, "Data from UNKNOWN");
1842 }
1843 const IDTypeInfo *id_type = BKE_idtype_get_info_from_idtype_index(id_type_index);
1844 const std::string alloc_string = fmt::format("Data from '{}' ID type", id_type->name);
1845 return storage.insert(id_type_index, alloc_string);
1846 }
1847 return storage.find(id_type_index);
1848 }
1849 return blockname;
1850#endif
1851}
1852
1853static void *read_struct(FileData *fd, BHead *bh, const char *blockname, const int id_type_index)
1854{
1855 void *temp = nullptr;
1856
1857 if (bh->len) {
1858#ifdef USE_BHEAD_READ_ON_DEMAND
1859 BHead *bh_orig = bh;
1860#endif
1861
1862 /* Endianness switch is based on file DNA.
1863 *
1864 * NOTE: raw data (aka #SDNA_RAW_DATA_STRUCT_INDEX #SDNAnr) is not handled here, it's up to
1865 * the calling code to manage this. */
1867 BLI_STATIC_ASSERT(SDNA_RAW_DATA_STRUCT_INDEX == 0, "'raw data' SDNA struct index should be 0")
1869#ifdef USE_BHEAD_READ_ON_DEMAND
1870 if (BHEADN_FROM_BHEAD(bh)->has_data == false) {
1871 bh = blo_bhead_read_full(fd, bh);
1872 if (UNLIKELY(bh == nullptr)) {
1873 fd->flags &= ~FD_FLAGS_FILE_OK;
1874 return nullptr;
1875 }
1876 }
1877#endif
1878 }
1879
1880 if (fd->compflags[bh->SDNAnr] != SDNA_CMP_REMOVED) {
1881 const char *alloc_name = get_alloc_name(fd, bh, blockname, id_type_index);
1882 if (fd->compflags[bh->SDNAnr] == SDNA_CMP_NOT_EQUAL) {
1883#ifdef USE_BHEAD_READ_ON_DEMAND
1884 if (BHEADN_FROM_BHEAD(bh)->has_data == false) {
1885 bh = blo_bhead_read_full(fd, bh);
1886 if (UNLIKELY(bh == nullptr)) {
1887 fd->flags &= ~FD_FLAGS_FILE_OK;
1888 return nullptr;
1889 }
1890 }
1891#endif
1893 fd->reconstruct_info, bh->SDNAnr, bh->nr, (bh + 1), alloc_name);
1894 }
1895 else {
1896 /* SDNA_CMP_EQUAL */
1897 const int alignment = DNA_struct_alignment(fd->filesdna, bh->SDNAnr);
1898 temp = MEM_mallocN_aligned(bh->len, alignment, alloc_name);
1899#ifdef USE_BHEAD_READ_ON_DEMAND
1900 if (BHEADN_FROM_BHEAD(bh)->has_data) {
1901 memcpy(temp, (bh + 1), bh->len);
1902 }
1903 else {
1904 /* Instead of allocating the bhead, then copying it,
1905 * read the data from the file directly into the memory. */
1906 if (UNLIKELY(!blo_bhead_read_data(fd, bh, temp))) {
1907 fd->flags &= ~FD_FLAGS_FILE_OK;
1908 MEM_freeN(temp);
1909 temp = nullptr;
1910 }
1911 }
1912#else
1913 memcpy(temp, (bh + 1), bh->len);
1914#endif
1915 }
1916 }
1917
1918#ifdef USE_BHEAD_READ_ON_DEMAND
1919 if (bh_orig != bh) {
1921 }
1922#endif
1923 }
1924
1925 return temp;
1926}
1927
1928static ID *read_id_struct(FileData *fd, BHead *bh, const char *blockname, const int id_type_index)
1929{
1930 ID *id = static_cast<ID *>(read_struct(fd, bh, blockname, id_type_index));
1931 if (!id) {
1932 return id;
1933 }
1934
1935 /* Invalid ID name (probably from 'too long' ID name from a future Blender version).
1936 *
1937 * They can only be truncated here, ensuring that all ID names remain unique happens later, after
1938 * reading all local IDs, but before linking them, see the call to
1939 * #long_id_names_ensure_unique_id_names in #blo_read_file_internal. */
1942 CLOG_DEBUG(&LOG, "Truncated too long ID name to '%s'", id->name);
1943 }
1944
1945 return id;
1946}
1947
1948/* Like read_struct, but gets a pointer without allocating. Only works for
1949 * undo since DNA must match. */
1950static const void *peek_struct_undo(FileData *fd, BHead *bhead)
1951{
1954 return (bhead->len) ? (const void *)(bhead + 1) : nullptr;
1955}
1956
1957static void link_glob_list(FileData *fd, ListBase *lb) /* for glob data */
1958{
1959 Link *ln, *prev;
1960 void *poin;
1961
1962 if (BLI_listbase_is_empty(lb)) {
1963 return;
1964 }
1965 poin = newdataadr(fd, lb->first);
1966 if (lb->first) {
1967 oldnewmap_insert(fd->globmap, lb->first, poin, 0);
1968 }
1969 lb->first = poin;
1970
1971 ln = static_cast<Link *>(lb->first);
1972 prev = nullptr;
1973 while (ln) {
1974 poin = newdataadr(fd, ln->next);
1975 if (ln->next) {
1976 oldnewmap_insert(fd->globmap, ln->next, poin, 0);
1977 }
1978 ln->next = static_cast<Link *>(poin);
1979 ln->prev = prev;
1980 prev = ln;
1981 ln = ln->next;
1982 }
1983 lb->last = prev;
1984}
1985
1987
1988/* -------------------------------------------------------------------- */
1991
1992static void after_liblink_id_process(BlendLibReader *reader, ID *id);
1993
1995{
1996
1997 /* Handle 'private IDs'. */
1999 if (nodetree != nullptr) {
2000 after_liblink_id_process(reader, &nodetree->id);
2001
2002 if (nodetree->owner_id == nullptr) {
2003 CLOG_WARN(&LOG,
2004 "NULL owner_id pointer for embedded NodeTree of %s, should never happen",
2005 id->name);
2006 nodetree->owner_id = id;
2007 }
2008 else if (nodetree->owner_id != id) {
2009 CLOG_WARN(&LOG,
2010 "Inconsistent owner_id pointer for embedded NodeTree of %s, should never happen",
2011 id->name);
2012 nodetree->owner_id = id;
2013 }
2014 }
2015
2016 if (GS(id->name) == ID_SCE) {
2017 Scene *scene = (Scene *)id;
2018 if (scene->master_collection != nullptr) {
2020
2021 if (scene->master_collection->owner_id == nullptr) {
2022 CLOG_WARN(&LOG,
2023 "NULL owner_id pointer for embedded Scene Collection of %s, should never happen",
2024 id->name);
2025 scene->master_collection->owner_id = id;
2026 }
2027 else if (scene->master_collection->owner_id != id) {
2028 CLOG_WARN(&LOG,
2029 "Inconsistent owner_id pointer for embedded Scene Collection of %s, should "
2030 "never happen",
2031 id->name);
2032 scene->master_collection->owner_id = id;
2033 }
2034 }
2035 }
2036}
2037
2039{
2040 /* NOTE: WM IDProperties are never written to file, hence they should always be nullptr here. */
2041 BLI_assert((GS(id->name) != ID_WM) || id->properties == nullptr);
2042
2044
2045 const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id);
2046 if (id_type->blend_read_after_liblink != nullptr) {
2047 id_type->blend_read_after_liblink(reader, id);
2048 }
2049}
2050
2053{
2054 BLO_read_string(reader, &op->rna_path);
2055
2056 op->tag = 0; /* Runtime only. */
2057
2059
2061 BLO_read_string(reader, &opop->subitem_reference_name);
2062 BLO_read_string(reader, &opop->subitem_local_name);
2063
2064 opop->tag = 0; /* Runtime only. */
2065 }
2066}
2067
2068static void direct_link_id_common(BlendDataReader *reader,
2069 Library *current_library,
2070 ID *id,
2071 ID *id_old,
2072 int id_tag,
2073 ID_Readfile_Data::Tags id_read_tags);
2074
2076 Library *current_library,
2077 ID *id,
2078 ID *id_old)
2079{
2080 /* Handle 'private IDs'. */
2081 if (GS(id->name) == ID_SCE) {
2082 Scene *scene = (Scene *)id;
2083 if (scene->compositing_node_group) {
2084 /* If `scene->compositing_node_group != nullptr`, then this means the blend file was created
2085 * by a version that wrote the compositing_node_group as its own ID datablock. Since
2086 * `scene->nodetree` was written for forward compatibility reasons only, we can ignore it. */
2087 scene->nodetree = nullptr;
2088 }
2089 }
2091 if (nodetree != nullptr && *nodetree != nullptr) {
2092 BLO_read_struct(reader, bNodeTree, nodetree);
2093 if (!*nodetree || !BKE_idtype_idcode_is_valid(GS((*nodetree)->id.name))) {
2095 reader->fd->reports,
2096 RPT_ERROR,
2097 RPT_("Data-block '%s' had an invalid embedded node group, which has not been read"),
2098 id->name);
2099 MEM_SAFE_FREE(*nodetree);
2100 }
2101 else {
2102 direct_link_id_common(reader,
2103 current_library,
2104 (ID *)*nodetree,
2105 id_old != nullptr ? (ID *)blender::bke::node_tree_from_id(id_old) :
2106 nullptr,
2107 0,
2109 blender::bke::node_tree_blend_read_data(reader, id, *nodetree);
2110 }
2111 }
2112
2113 if (GS(id->name) == ID_SCE) {
2114 Scene *scene = (Scene *)id;
2115 if (scene->master_collection != nullptr) {
2117 if (!scene->master_collection ||
2119 {
2121 reader->fd->reports,
2122 RPT_ERROR,
2123 RPT_("Scene '%s' had an invalid root collection, which has not been read"),
2124 BKE_id_name(*id));
2126 }
2127 else {
2128 direct_link_id_common(reader,
2129 current_library,
2130 &scene->master_collection->id,
2131 id_old != nullptr ? &((Scene *)id_old)->master_collection->id :
2132 nullptr,
2133 0,
2135 BKE_collection_blend_read_data(reader, scene->master_collection, &scene->id);
2136 }
2137 }
2138 }
2139}
2140
2142{
2143 /* Exception for armature objects, where the pose has direct points to the
2144 * armature data-block. */
2145 if (GS(id_current->name) == ID_OB && ((Object *)id_current)->pose) {
2146 return ID_RECALC_GEOMETRY;
2147 }
2148
2149 return 0;
2150}
2151
2153 const ID *id_target,
2154 const ID *id_current,
2155 const bool is_identical)
2156{
2157 /* These are the evaluations that had not been performed yet at the time the
2158 * target undo state was written. These need to be done again, since they may
2159 * flush back changes to the original datablock. */
2160 int recalc = id_target->recalc;
2161
2162 if (id_current == nullptr) {
2163 /* ID does not currently exist in the database, so also will not exist in
2164 * the dependency graphs. That means it will be newly created and as a
2165 * result also fully re-evaluated regardless of the recalc flag set here. */
2166 recalc |= ID_RECALC_ALL;
2167 }
2168 else {
2169 /* If the contents datablock changed, the depsgraph needs to copy the
2170 * datablock again to ensure it matches the original datablock. */
2171 if (!is_identical) {
2172 recalc |= ID_RECALC_SYNC_TO_EVAL;
2173 }
2174
2175 /* Special exceptions. */
2176 recalc |= direct_link_id_restore_recalc_exceptions(id_current);
2177
2178 /* Evaluations for the current state that have not been performed yet
2179 * by the time we are performing this undo step. */
2180 recalc |= id_current->recalc;
2181
2182 /* Tags that were set between the target state and the current state,
2183 * that we need to perform again. */
2184 if (fd->undo_direction == STEP_UNDO) {
2185 /* Undo: tags from target to the current state. */
2186 recalc |= id_current->recalc_up_to_undo_push;
2187 }
2188 else {
2190 /* Redo: tags from current to the target state. */
2191 recalc |= id_target->recalc_up_to_undo_push;
2192 }
2193 }
2194
2195 return recalc;
2196}
2197
2199{
2200 if (id.runtime->readfile_data) {
2201 return;
2202 }
2203 id.runtime->readfile_data = MEM_callocN<ID_Readfile_Data>(__func__);
2204}
2205
2207{
2208 if (!id.runtime->readfile_data) {
2209 return ID_Readfile_Data::Tags{};
2210 }
2211 return id.runtime->readfile_data->tags;
2212}
2213
2215{
2217 return id.runtime->readfile_data->tags;
2218}
2219
2221{
2222 MEM_SAFE_FREE(id.runtime->readfile_data);
2223}
2224
2226{
2227 ID *id;
2228 FOREACH_MAIN_ID_BEGIN (&bmain, id) {
2229 /* Handle the ID itself. */
2231
2232 /* Handle its embedded IDs, because they do not get referenced by bmain. */
2233 if (GS(id->name) == ID_SCE) {
2234 Collection *collection = reinterpret_cast<Scene *>(id)->master_collection;
2235 if (collection) {
2237 }
2238 }
2239
2241 if (node_tree) {
2243 }
2244 }
2246}
2247
2249 Library *current_library,
2250 ID *id,
2251 ID *id_old,
2252 const int id_tag,
2253 const ID_Readfile_Data::Tags id_read_tags)
2254{
2255 /* This should have been caught already, either by a call to `#blo_bhead_is_id_valid_type` for
2256 * regular IDs, or in `#direct_link_id_embedded_id` for embedded ones. */
2258 "Unknown or invalid ID type, this should never happen");
2259
2260 BLI_assert(id->runtime == nullptr);
2262
2263 if (!BLO_read_data_is_undo(reader)) {
2264 /* When actually reading a file, we do want to reset/re-generate session UIDS.
2265 * In undo case, we want to re-use existing ones. */
2266 id->session_uid = MAIN_ID_SESSION_UID_UNSET;
2267 }
2268
2269 if (id->flag & ID_FLAG_LINKED_AND_PACKED) {
2270 if (!current_library) {
2271 CLOG_ERROR(&LOG,
2272 "Data-block '%s' flagged as packed, but without a valid library, fixing by "
2273 "making fully local...",
2274 id->name);
2275 id->flag &= ~ID_FLAG_LINKED_AND_PACKED;
2276 }
2277 else if ((current_library->flag & LIBRARY_FLAG_IS_ARCHIVE) == 0) {
2278 CLOG_ERROR(&LOG,
2279 "Data-block '%s' flagged as packed, but using a regular library, fixing by "
2280 "making fully linked...",
2281 id->name);
2282 id->flag &= ~ID_FLAG_LINKED_AND_PACKED;
2283 }
2284 }
2285 id->lib = current_library;
2286 if (id->lib) {
2287 /* Always fully clear fake user flag for linked data. */
2288 id->flag &= ~ID_FLAG_FAKEUSER;
2289 }
2290 id->us = ID_FAKE_USERS(id);
2291 id->icon_id = 0;
2292 id->newid = nullptr; /* Needed because .blend may have been saved with crap value here... */
2293 id->orig_id = nullptr;
2294 id->py_instance = nullptr;
2295
2296 /* Initialize with provided tag. */
2297 if (BLO_read_data_is_undo(reader)) {
2298 id->tag = (id_tag & ~ID_TAG_KEEP_ON_UNDO) | (id->tag & ID_TAG_KEEP_ON_UNDO);
2299 }
2300 else {
2301 id->tag = id_tag;
2302 }
2303
2305 id->runtime->readfile_data->tags = id_read_tags;
2306
2307 if ((id_tag & ID_TAG_TEMP_MAIN) == 0) {
2309 }
2310
2311 if (ID_IS_LINKED(id)) {
2312 id->library_weak_reference = nullptr;
2313 }
2314 else {
2316 }
2317
2319 /* For placeholder we only need to set the tag and properly initialize generic ID fields above,
2320 * no further data to read. */
2321 return;
2322 }
2323
2324 BKE_animdata_blend_read_data(reader, id);
2325
2326 if (id->asset_data) {
2329 /* Restore runtime asset type info. */
2330 const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id);
2331 id->asset_data->local_type_info = id_type->asset_type_info;
2332 }
2333
2334 /* Link direct data of ID properties. */
2335 if (id->properties) {
2336 BLO_read_struct(reader, IDProperty, &id->properties);
2337 /* this case means the data was written incorrectly, it should not happen */
2338 IDP_BlendDataRead(reader, &id->properties);
2339 }
2340
2341 if (id->system_properties) {
2344 }
2345
2346 id->flag &= ~ID_FLAG_INDIRECT_WEAK_LINK;
2347
2348 /* NOTE: It is important to not clear the recalc flags for undo/redo.
2349 * Preserving recalc flags on redo/undo is the only way to make dependency graph detect
2350 * that animation is to be evaluated on undo/redo. If this is not enforced by the recalc
2351 * flags dependency graph does not do animation update to avoid loss of unkeyed changes.,
2352 * which conflicts with undo/redo of changes to animation data itself.
2353 *
2354 * But for regular file load we clear the flag, since the flags might have been changed since
2355 * the version the file has been saved with. */
2356 if (!BLO_read_data_is_undo(reader)) {
2357 id->recalc = 0;
2358 id->recalc_after_undo_push = 0;
2359 }
2360 else if ((reader->fd->skip_flags & BLO_READ_SKIP_UNDO_OLD_MAIN) == 0) {
2361 id->recalc = direct_link_id_restore_recalc(reader->fd, id, id_old, false);
2362 id->recalc_after_undo_push = 0;
2363 }
2364
2365 /* Link direct data of overrides. */
2366 if (id->override_library) {
2368 /* Work around file corruption on writing, see #86853. */
2369 if (id->override_library != nullptr) {
2373 }
2374 id->override_library->runtime = nullptr;
2375 }
2376 }
2377
2378 /* Handle 'private IDs'. */
2379 direct_link_id_embedded_id(reader, current_library, id, id_old);
2380}
2381
2383
2384/* -------------------------------------------------------------------- */
2387
2389
2390/* -------------------------------------------------------------------- */
2393
2395{
2396 key->uidgen = 1;
2397 LISTBASE_FOREACH (KeyBlock *, block, &key->block) {
2398 block->uid = key->uidgen++;
2399 }
2400}
2401
2403
2404/* -------------------------------------------------------------------- */
2407
2408#ifdef USE_SETSCENE_CHECK
2412static bool scene_validate_setscene__liblink(Scene *sce, const int totscene)
2413{
2414 Scene *sce_iter;
2415 int a;
2416
2417 if (sce->set == nullptr) {
2418 return true;
2419 }
2420
2421 for (a = 0, sce_iter = sce; sce_iter->set; sce_iter = sce_iter->set, a++) {
2422 /* This runs per library (before each libraries #Main has been joined),
2423 * so we can't step into other libraries since `totscene` is only for this library.
2424 *
2425 * Also, other libraries may not have been linked yet, while we could check for
2426 * #ID_Readfile_Data::Tags.needs_linking the library pointer check is sufficient. */
2427 if (sce->id.lib != sce_iter->id.lib) {
2428 return true;
2429 }
2431 return true;
2432 }
2433
2434 if (a > totscene) {
2435 sce->set = nullptr;
2436 return false;
2437 }
2438 }
2439
2440 return true;
2441}
2442#endif
2443
2445{
2446#ifdef USE_SETSCENE_CHECK
2447 const int totscene = BLI_listbase_count(&bmain->scenes);
2448 LISTBASE_FOREACH (Scene *, sce, &bmain->scenes) {
2451 if (!scene_validate_setscene__liblink(sce, totscene)) {
2452 CLOG_WARN(&LOG, "Found cyclic background scene when linking %s", sce->id.name + 2);
2453 }
2454 }
2455 }
2456#else
2457 UNUSED_VARS(bmain, totscene);
2458#endif
2459}
2460
2461#undef USE_SETSCENE_CHECK
2462
2464
2465/* -------------------------------------------------------------------- */
2466
2469
2471{
2472 if (lib->runtime->filedata) {
2473 BLI_assert(lib->runtime->versionfile != 0);
2474 BLI_assert_msg(!lib->runtime->is_filedata_owner || (lib->flag & LIBRARY_FLAG_IS_ARCHIVE) == 0,
2475 "Packed Archive libraries should never own their filedata");
2476 if (lib->runtime->is_filedata_owner) {
2477 blo_filedata_free(lib->runtime->filedata);
2478 }
2479
2480 lib->runtime->filedata = nullptr;
2481 }
2482 lib->runtime->is_filedata_owner = false;
2483}
2484
2486{
2487 /* Make sure we have full path in lib->runtime->filepath_abs */
2488 /* NOTE: Since existing libraries are searched by their absolute path, this has to be generated
2489 * before the lookup below. Otherwise, in case the stored absolute filepath is not 'correct' (may
2490 * be empty, or have been stored in a different 'relative path context'), the comparison below
2491 * will always fail, leading to creating duplicates IDs of a same library. */
2492 /* TODO: May be worth checking whether comparison below could use `lib->filepath` instead? */
2493 STRNCPY(lib->runtime->filepath_abs, lib->filepath);
2494 BLI_path_abs(lib->runtime->filepath_abs, fd->relabase);
2495 BLI_path_normalize(lib->runtime->filepath_abs);
2496
2497 /* check if the library was already read */
2498 for (Main *newmain : *fd->bmain->split_mains) {
2499 if (!newmain->curlib) {
2500 continue;
2501 }
2502 if (newmain->curlib->flag & LIBRARY_FLAG_IS_ARCHIVE || lib->flag & LIBRARY_FLAG_IS_ARCHIVE) {
2503 /* Archive library should never be used to link new data, and there can be many such
2504 * archive libraries for a same 'real' blendfile one. */
2505 continue;
2506 }
2507 if (BLI_path_cmp(newmain->curlib->runtime->filepath_abs, lib->runtime->filepath_abs) == 0) {
2510 RPT_("Library '%s', '%s' had multiple instances, save and reload!"),
2511 lib->filepath,
2512 lib->runtime->filepath_abs);
2513
2515 // change_link_placeholder_to_real_ID_pointer_fd(fd, lib, newmain->curlib);
2516
2517 BLI_remlink(&main->libraries, lib);
2518 MEM_freeN(lib);
2519
2520 /* Now, since Blender always expect **last** Main pointer from fd->bmain->split_mains
2521 * to be the active library Main pointer, where to add all non-library data-blocks found in
2522 * file next, we have to switch that 'dupli' found Main to latest position in the list!
2523 * Otherwise, you get weird disappearing linked data on a rather inconsistent basis.
2524 * See also #53977 for reproducible case. */
2525 /* Note: the change in order in `fd->bmain->split_mains` should not be an issue here, and we
2526 * return immediately. */
2527 fd->bmain->split_mains->remove_contained(newmain);
2528 fd->bmain->split_mains->add_new(newmain);
2529 BLI_assert((*fd->bmain->split_mains)[0] == fd->bmain);
2530
2531 return;
2532 }
2533 }
2534
2535 // printf("direct_link_library: filepath %s\n", lib->filepath);
2536 // printf("direct_link_library: filepath_abs %s\n", lib->runtime->filepath_abs);
2537
2538 BlendDataReader reader = {fd};
2539 BKE_packedfile_blend_read(&reader, &lib->packedfile, lib->filepath);
2540
2541 /* new main */
2542 Main *newmain = BKE_main_new();
2543 fd->bmain->split_mains->add_new(newmain);
2544 newmain->split_mains = fd->bmain->split_mains;
2545 newmain->curlib = lib;
2546
2547 if (lib->flag & LIBRARY_FLAG_IS_ARCHIVE) {
2548 /* Archive libraries contains only embedded linked IDs, which by definition have the same
2549 * fileversion as the blendfile that contains them. */
2550 lib->runtime->versionfile = newmain->versionfile = fd->bmain->versionfile;
2551 lib->runtime->subversionfile = newmain->subversionfile = fd->bmain->subversionfile;
2552
2553 /* The filedata of a packed archive library should always be the one of the blendfile which
2554 * defines the library ID and packs its linked IDs. */
2555 lib->runtime->filedata = fd;
2556 lib->runtime->is_filedata_owner = false;
2557 }
2558
2559 lib->runtime->parent = nullptr;
2560
2561 id_us_ensure_real(&lib->id);
2562
2563 /* Should always be null, Library IDs in Blender are always local. */
2564 lib->id.lib = nullptr;
2565}
2566
2567/* Always call this once you have loaded new library data to set the relative paths correctly
2568 * in relation to the blend file. */
2569static void fix_relpaths_library(const char *basepath, Main *main)
2570{
2571 /* #BLO_read_from_memory uses a blank file-path. */
2572 if (basepath == nullptr || basepath[0] == '\0') {
2573 LISTBASE_FOREACH (Library *, lib, &main->libraries) {
2574 /* when loading a linked lib into a file which has not been saved,
2575 * there is nothing we can be relative to, so instead we need to make
2576 * it absolute. This can happen when appending an object with a relative
2577 * link into an unsaved blend file. See #27405.
2578 * The remap relative option will make it relative again on save - campbell */
2579 if (BLI_path_is_rel(lib->filepath)) {
2580 STRNCPY(lib->filepath, lib->runtime->filepath_abs);
2581 }
2582 }
2583 }
2584 else {
2585 LISTBASE_FOREACH (Library *, lib, &main->libraries) {
2586 /* Libraries store both relative and abs paths, recreate relative paths,
2587 * relative to the blend file since indirectly linked libraries will be
2588 * relative to their direct linked library. */
2589 if (BLI_path_is_rel(lib->filepath)) { /* if this is relative to begin with? */
2590 STRNCPY(lib->filepath, lib->runtime->filepath_abs);
2591 BLI_path_rel(lib->filepath, basepath);
2592 }
2593 }
2594 }
2595}
2596
2598
2599/* -------------------------------------------------------------------- */
2602
2603static ID *create_placeholder(Main *mainvar,
2604 const short idcode,
2605 const char *idname,
2606 const int tag,
2607 const bool was_liboverride)
2608{
2609 ListBase *lb = which_libbase(mainvar, idcode);
2610 ID *ph_id = BKE_libblock_alloc_notest(idcode);
2612
2613 *((short *)ph_id->name) = idcode;
2614 BLI_strncpy(ph_id->name + 2, idname, sizeof(ph_id->name) - 2);
2616 ph_id->lib = mainvar->curlib;
2617 ph_id->tag = tag | ID_TAG_MISSING;
2618 ph_id->us = ID_FAKE_USERS(ph_id);
2619 ph_id->icon_id = 0;
2620
2621 if (was_liboverride) {
2622 /* 'Abuse' `ID_TAG_LIBOVERRIDE_NEED_RESYNC` to mark that placeholder missing linked ID as
2623 * being a liboverride.
2624 *
2625 * This will be used by the liboverride resync process, see #lib_override_library_resync. */
2627 }
2628
2629 BLI_addtail(lb, ph_id);
2630 id_sort_by_name(lb, ph_id, nullptr);
2631
2632 if (mainvar->id_map != nullptr) {
2633 BKE_main_idmap_insert_id(mainvar->id_map, ph_id);
2634 }
2635
2636 if ((tag & ID_TAG_TEMP_MAIN) == 0) {
2638 }
2639
2640 return ph_id;
2641}
2642
2644{
2645 /* Placeholder ObData IDs won't have any material, we have to update their objects for that,
2646 * otherwise the inconsistency between both will lead to crashes (especially in Eevee?). */
2647 LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
2648 ID *obdata = static_cast<ID *>(ob->data);
2649 if (obdata != nullptr && obdata->tag & ID_TAG_MISSING) {
2650 BKE_object_materials_sync_length(bmain, ob, obdata);
2651 }
2652 }
2653}
2654
2655static bool direct_link_id(FileData *fd,
2656 Main *main,
2657 const int tag,
2658 const ID_Readfile_Data::Tags id_read_tags,
2659 ID *id,
2660 ID *id_old)
2661{
2662 BlendDataReader reader = {fd};
2663 /* Sharing is only allowed within individual data-blocks currently. The clearing is done
2664 * explicitly here, in case the `reader` is used by multiple IDs in the future. */
2666
2667 /* Read part of datablock that is common between real and embedded datablocks. */
2668 direct_link_id_common(&reader, main->curlib, id, id_old, tag, id_read_tags);
2669
2671 /* For placeholder we only need to set the tag, no further data to read. */
2672 id->tag = tag;
2673 return true;
2674 }
2675
2676 const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id);
2677 if (id_type->blend_read_data != nullptr) {
2678 id_type->blend_read_data(&reader, id);
2679 }
2680
2681 /* XXX Very weakly handled currently, see comment in read_libblock() before trying to
2682 * use it for anything new. */
2683 bool success = true;
2684
2685 switch (GS(id->name)) {
2686 case ID_SCR:
2687 success = BKE_screen_blend_read_data(&reader, (bScreen *)id);
2688 break;
2689 case ID_LI:
2690 direct_link_library(fd, (Library *)id, main);
2691 break;
2692 default:
2693 /* Do nothing. Handled by IDTypeInfo callback. */
2694 break;
2695 }
2696
2697 /* try to restore (when undoing) or clear ID's cache pointers. */
2698 if (id_type->foreach_cache != nullptr) {
2701 }
2702
2703 return success;
2704}
2705
2706/* Read all data associated with a datablock into datamap. */
2708 BHead *bhead,
2709 const char *allocname,
2710 const int id_type_index)
2711{
2712 bhead = blo_bhead_next(fd, bhead);
2713
2714 while (bhead && bhead->code == BLO_CODE_DATA) {
2715 void *data = read_struct(fd, bhead, allocname, id_type_index);
2716 if (data) {
2717 const bool is_new = oldnewmap_insert(fd->datamap, bhead->old, data, 0);
2718 if (!is_new) {
2719 CLOG_ERROR(&LOG,
2720 "Blendfile corruption: Invalid, or multiple `bhead` with same old address "
2721 "value (%p) for a given ID.",
2722 bhead->old);
2723 }
2724 }
2725
2726 bhead = blo_bhead_next(fd, bhead);
2727 }
2728
2729 return bhead;
2730}
2731
2732/* Add a Main (and optionally create a matching Library ID), for the given filepath.
2733 *
2734 * - If `lib` is `nullptr`, create a new Library ID, otherwise only create a new Main for the given
2735 * library.
2736 * - `reference_lib` is the 'archive parent' of an archive (packed) library, can be null and will
2737 * be ignored otherwise. */
2739 Library *lib,
2740 Library *reference_lib,
2741 const char *lib_filepath,
2742 char (&filepath_abs)[FILE_MAX],
2743 const bool is_packed_library)
2744{
2745 Main *bmain = BKE_main_new();
2746 fd->bmain->split_mains->add_new(bmain);
2747 bmain->split_mains = fd->bmain->split_mains;
2748
2749 if (!lib) {
2750 /* Add library data-block itself to 'main' Main, since libraries are **never** linked data.
2751 * Fixes bug where you could end with all ID_LI data-blocks having the same name... */
2753 reference_lib ? BKE_id_name(reference_lib->id) :
2754 BLI_path_basename(lib_filepath));
2755
2756 /* Important, consistency with main ID reading code from read_libblock(). */
2757 lib->id.us = ID_FAKE_USERS(lib);
2758
2759 /* Matches direct_link_library(). */
2760 id_us_ensure_real(&lib->id);
2761
2762 STRNCPY(lib->filepath, lib_filepath);
2763 STRNCPY(lib->runtime->filepath_abs, filepath_abs);
2764
2765 if (is_packed_library) {
2766 /* FIXME: This logic is very similar to the code in BKE_library dealing with archived
2767 * libraries (e.g. #add_archive_library). Might be good to try to factorize it. */
2768 lib->archive_parent_library = reference_lib;
2769 constexpr uint16_t copy_flag = ~LIBRARY_FLAG_IS_ARCHIVE;
2770 lib->flag = (reference_lib->flag & copy_flag) | LIBRARY_FLAG_IS_ARCHIVE;
2771
2772 lib->runtime->parent = reference_lib->runtime->parent;
2773 /* Only copy a subset of the reference library tags. E.g. an archive library should never be
2774 * considered as writable, so never copy #LIBRARY_ASSET_FILE_WRITABLE. This may need further
2775 * tweaking still. */
2776 constexpr uint16_t copy_tag = (LIBRARY_TAG_RESYNC_REQUIRED | LIBRARY_ASSET_EDITABLE |
2778 lib->runtime->tag = reference_lib->runtime->tag & copy_tag;
2779
2780 /* The filedata of a packed archive library should always be the one of the blendfile which
2781 * defines the library ID and packs its linked IDs. */
2782 lib->runtime->filedata = fd;
2783 lib->runtime->is_filedata_owner = false;
2784
2785 reference_lib->runtime->archived_libraries.append(lib);
2786 }
2787 }
2788 else {
2789 if (is_packed_library) {
2791 BLI_assert(lib->archive_parent_library == reference_lib);
2792
2793 /* If there is already an archive library in the new set of Mains, but not a 'libmain' for it
2794 * yet, it is the first time that this archive library is effectively used to own a packed
2795 * ID. Since regular libraries have their list of owned archive libs cleared when reused on
2796 * undo, it means that this archive library should yet be listed in its regular owner one,
2797 * and needs to be added there. See also #read_undo_move_libmain_data. */
2798 BLI_assert(!reference_lib->runtime->archived_libraries.contains(lib));
2799 reference_lib->runtime->archived_libraries.append(lib);
2800
2801 BLI_assert(lib->runtime->filedata == nullptr);
2802 lib->runtime->filedata = fd;
2803 lib->runtime->is_filedata_owner = false;
2804 }
2805 else {
2806 /* Should never happen currently. */
2808 }
2809 }
2810
2811 bmain->curlib = lib;
2812 return bmain;
2813}
2814
2815/* Verify if the datablock and all associated data is identical. */
2817{
2818 /* Test ID itself. */
2819 if (bhead->len && !BHEADN_FROM_BHEAD(bhead)->is_memchunk_identical) {
2820 return false;
2821 }
2822
2823 /* Test any other data that is part of ID (logic must match read_data_into_datamap). */
2824 bhead = blo_bhead_next(fd, bhead);
2825
2826 while (bhead && bhead->code == BLO_CODE_DATA) {
2827 if (bhead->len && !BHEADN_FROM_BHEAD(bhead)->is_memchunk_identical) {
2828 return false;
2829 }
2830
2831 bhead = blo_bhead_next(fd, bhead);
2832 }
2833
2834 return true;
2835}
2836
2837/* Re-use the whole 'noundo' local IDs by moving them from old to new main. Linked ones are handled
2838 * separately together with their libraries.
2839 *
2840 * NOTE: While in theory Library IDs (and their related linked IDs) are also 'noundo' data, in
2841 * practice they need to be handled separately, to ensure that their order in the new bmain list
2842 * matches the one from the read blend-file. Reading linked 'placeholder' entries in a memfile
2843 * relies on current library being the last item in the new main list. */
2845{
2846 Main *new_bmain = fd->bmain;
2847 Main *old_bmain = fd->old_bmain;
2848
2849 BLI_assert(old_bmain->curlib == nullptr);
2850 BLI_assert(old_bmain->split_mains);
2851
2852 MainListsArray lbarray = BKE_main_lists_get(*old_bmain);
2853 int i = lbarray.size();
2854 while (i--) {
2855 if (BLI_listbase_is_empty(lbarray[i])) {
2856 continue;
2857 }
2858
2859 /* Only move 'noundo' local IDs. */
2860 ID *id = static_cast<ID *>(lbarray[i]->first);
2861 const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id);
2862 if ((id_type->flags & IDTYPE_FLAGS_NO_MEMFILE_UNDO) == 0) {
2863 continue;
2864 }
2865
2866 ListBase *new_lb = which_libbase(new_bmain, id_type->id_code);
2868 BLI_movelisttolist(new_lb, lbarray[i]);
2869
2870 /* Update mappings accordingly. */
2871 LISTBASE_FOREACH (ID *, id_iter, new_lb) {
2873 id_iter->tag |= ID_TAG_UNDO_OLD_ID_REUSED_NOUNDO;
2874 }
2875 }
2876}
2877
2878static void read_undo_move_libmain_data(FileData *fd, Main *libmain, BHead *bhead)
2879{
2880 Main *old_main = fd->old_bmain;
2881 Main *new_main = fd->bmain;
2882 Library *curlib = libmain->curlib;
2883
2884 /* NOTE: This may change the order of items in `old_main->split_mains`. So calling code cannot
2885 * directly iterate over it. */
2886 old_main->split_mains->remove_contained(libmain);
2887 BLI_remlink_safe(&old_main->libraries, curlib);
2888 new_main->split_mains->add_new(libmain);
2889 BLI_addtail(&new_main->libraries, curlib);
2890
2891 /* Remove all references to the archive libraries owned by this 'regular' library. The
2892 * archive ones are only moved over into the new Main if some of their IDs are actually
2893 * re-used. Otherwise they are deleted, so the 'regular' library cannot keep references to
2894 * them at this point. See also #blo_add_main_for_library. */
2895 curlib->runtime->archived_libraries = {};
2896
2899 if (bhead != nullptr) {
2900 oldnewmap_lib_insert(fd, bhead->old, &curlib->id, GS(curlib->id.name));
2901 }
2902
2903 ID *id_iter;
2904 FOREACH_MAIN_ID_BEGIN (libmain, id_iter) {
2905 /* Packed IDs are read from the memfile, so don't add them here already. */
2906 if (!ID_IS_PACKED(id_iter)) {
2908 }
2909 }
2911}
2912
2913/* For undo, restore matching library datablock from the old main. */
2915 const ID *id,
2916 ID *id_old,
2917 BHead *bhead)
2918{
2919 /* In undo case, most libraries and linked data should be kept as is from previous state
2920 * (see BLO_read_from_memfile).
2921 * However, some needed by the snapshot being read may have been removed in previous one,
2922 * and would go missing.
2923 * This leads e.g. to disappearing objects in some undo/redo case, see #34446.
2924 * That means we have to carefully check whether current lib or
2925 * libdata already exits in old main, if it does we merely copy it over into new main area,
2926 * otherwise we have to do a full read of that bhead... */
2927 CLOG_DEBUG(&LOG_UNDO, "UNDO: restore library %s", id->name);
2928
2929 if (id_old == nullptr) {
2930 CLOG_DEBUG(&LOG_UNDO, " -> NO match");
2931 return false;
2932 }
2933
2934 /* Skip `oldmain` itself. */
2935 /* NOTE: Only one item is removed from `old_main->split_mains`, so it is safe to iterate directly
2936 * on it here. The fact that the order of the other mains contained in this split_mains may be
2937 * modified should not be an issue currently. */
2938 for (Main *libmain : fd->old_bmain->split_mains->as_span().drop_front(1)) {
2939 if (&libmain->curlib->id == id_old) {
2940 BLI_assert(libmain->curlib);
2941 BLI_assert((libmain->curlib->flag & LIBRARY_FLAG_IS_ARCHIVE) == 0);
2943 " compare with %s -> match (existing libpath: %s)",
2944 libmain->curlib->id.name,
2945 libmain->curlib->runtime->filepath_abs);
2946
2947 /* In case of a library, we need to re-add its main to fd->bmain->split_mains,
2948 * because if we have later a missing ID_LINK_PLACEHOLDER,
2949 * we need to get the correct lib it is linked to!
2950 * Order is crucial, we cannot bulk-add it in BLO_read_from_memfile()
2951 * like it used to be. */
2952 read_undo_move_libmain_data(fd, libmain, bhead);
2954 BLI_assert(fd->old_bmain->split_mains->size() >= 1);
2955 BLI_assert((*fd->old_bmain->split_mains)[0] == fd->old_bmain);
2956 return true;
2957 }
2958 }
2959
2960 return false;
2961}
2962
2963static ID *library_id_is_yet_read(FileData *fd, Main *mainvar, BHead *bhead);
2964
2965/* For undo, restore existing linked datablock from the old main.
2966 *
2967 * Note that IDs from existing libs have already been moved into the new main when their (local)
2968 * ID_LI library ID was handled by #read_libblock_undo_restore_library, so this function has very
2969 * little to do. */
2971 FileData *fd, Main *libmain, const ID *id, ID **r_id_old, BHead *bhead)
2972{
2973 CLOG_DEBUG(&LOG_UNDO, "UNDO: restore linked datablock %s", id->name);
2974
2975 if (*r_id_old == nullptr) {
2976 /* If the linked ID had to be re-read at some point, its session_uid may not be the same as
2977 * its reference stored in the memfile anymore. Do a search by name then. */
2978 *r_id_old = library_id_is_yet_read(fd, libmain, bhead);
2979
2980 if (*r_id_old == nullptr) {
2982 " from %s (%s): NOT found",
2983 libmain->curlib ? libmain->curlib->id.name : "<nullptr>",
2984 libmain->curlib ? libmain->curlib->filepath : "<nullptr>");
2985 return false;
2986 }
2987
2989 " from %s (%s): found by name",
2990 libmain->curlib ? libmain->curlib->id.name : "<nullptr>",
2991 libmain->curlib ? libmain->curlib->filepath : "<nullptr>");
2992 /* The Library ID 'owning' this linked ID should already have been moved to new main by a call
2993 * to #read_libblock_undo_restore_library. */
2994 BLI_assert(*r_id_old == static_cast<ID *>(BKE_main_idmap_lookup_uid(
2995 fd->new_idmap_uid, (*r_id_old)->session_uid)));
2996 }
2997 else {
2999 " from %s (%s): found by session_uid",
3000 libmain->curlib ? libmain->curlib->id.name : "<nullptr>",
3001 libmain->curlib ? libmain->curlib->filepath : "<nullptr>");
3002 /* The Library ID 'owning' this linked ID should already have been moved to new main by a call
3003 * to #read_libblock_undo_restore_library. */
3004 BLI_assert(*r_id_old ==
3005 static_cast<ID *>(BKE_main_idmap_lookup_uid(fd->new_idmap_uid, id->session_uid)));
3006 }
3007
3008 oldnewmap_lib_insert(fd, bhead->old, *r_id_old, GS((*r_id_old)->name));
3009
3010 /* No need to do anything else for ID_LINK_PLACEHOLDER, it's assumed
3011 * already present in its lib's main. */
3012 return true;
3013}
3014
3015/* For undo, restore unchanged local datablock from old main. */
3017 FileData *fd, Main *main, const ID * /*id*/, ID *id_old, BHead *bhead, const int id_tag)
3018{
3020 BLI_assert(id_old != nullptr);
3021
3022 /* Do not add ID_TAG_NEW here, this should not be needed/used in undo case anyway (as
3023 * this is only for do_version-like code), but for sake of consistency, and also because
3024 * it will tell us which ID is re-used from old Main, and which one is actually newly read. */
3025 /* Also do not set #ID_Readfile_Data::Tags.needs_linking, this ID will never be re-liblinked,
3026 * hence that tag will never be cleared, leading to critical issue in link/append code. */
3027 /* Some tags need to be preserved here. */
3029 (id_old->tag & ID_TAG_KEEP_ON_UNDO);
3030 id_old->lib = main->curlib;
3031 id_old->us = ID_FAKE_USERS(id_old);
3032 /* Do not reset id->icon_id here, memory allocated for it remains valid. */
3033 /* Needed because .blend may have been saved with crap value here... */
3034 id_old->newid = nullptr;
3035 id_old->orig_id = nullptr;
3036
3037 const short idcode = GS(id_old->name);
3038 Main *old_bmain = fd->old_bmain;
3039 ListBase *old_lb = which_libbase(old_bmain, idcode);
3040 ListBase *new_lb = which_libbase(main, idcode);
3041 BLI_remlink(old_lb, id_old);
3042 BLI_addtail(new_lb, id_old);
3043
3044 /* Recalc flags, mostly these just remain as they are. */
3046 id_old->recalc_after_undo_push = 0;
3047
3048 /* Insert into library map for lookup by newly read datablocks (with pointer value bhead->old).
3049 * Note that existing datablocks in memory (which pointer value would be id_old) are not
3050 * remapped, so no need to store this info here. */
3051 oldnewmap_lib_insert(fd, bhead->old, id_old, bhead->code);
3052
3054
3055 if (GS(id_old->name) == ID_OB) {
3056 Object *ob = (Object *)id_old;
3057 /* For undo we stay in object mode during undo presses, so keep editmode disabled for re-used
3058 * data-blocks too. */
3059 ob->mode &= ~OB_MODE_EDIT;
3060 }
3061 if (GS(id_old->name) == ID_LI) {
3062 Library *lib = reinterpret_cast<Library *>(id_old);
3063 if (lib->flag & LIBRARY_FLAG_IS_ARCHIVE) {
3064 BLI_assert(lib->runtime->filedata == nullptr);
3065 BLI_assert(lib->archive_parent_library);
3066 /* The 'normal' parent of this archive library should already have been moved into the new
3067 * Main. */
3069 lib->archive_parent_library->id.session_uid) ==
3070 &lib->archive_parent_library->id);
3071 /* The archive library ID has been moved in the new Main, but not its own old split main, as
3072 * these packed IDs should be handled like local ones in undo case. So a new split libmain
3073 * needs to be created to contain its packed IDs. */
3075 fd, lib, lib->archive_parent_library, lib->filepath, lib->runtime->filepath_abs, true);
3076 }
3077 else {
3079 }
3080 }
3081}
3082
3083/* For undo, store changed datablock at old address. */
3085{
3086 /* During memfile undo, if an ID changed and we cannot directly re-use existing one from old
3087 * bmain, we do a full read of the new id from the memfile, and then fully swap its content
3088 * with the old id. This allows us to keep the same pointer even for modified data, which
3089 * helps reducing further detected changes by the depsgraph (since unchanged IDs remain fully
3090 * unchanged, even if they are using/pointing to a changed one). */
3092 BLI_assert(id_old != nullptr);
3093
3094 const short idcode = GS(id->name);
3095
3096 Main *old_bmain = fd->old_bmain;
3097 ListBase *old_lb = which_libbase(old_bmain, idcode);
3098 ListBase *new_lb = which_libbase(main, idcode);
3099 BLI_remlink(old_lb, id_old);
3100 BLI_remlink(new_lb, id);
3101
3102 /* We do need remapping of internal pointers to the ID itself here.
3103 *
3104 * Passing a null #Main means that not all potential runtime data (like collections' parent
3105 * pointers etc.) will be up-to-date. However, this should not be a problem here, since these
3106 * data are re-generated later in file-read process anyway. */
3107 BKE_lib_id_swap_full(nullptr,
3108 id,
3109 id_old,
3110 true,
3114
3115 /* Special temporary usage of this pointer, necessary for the `undo_preserve` call after
3116 * lib-linking to restore some data that should never be affected by undo, e.g. the 3D cursor of
3117 * #Scene. */
3118 id_old->orig_id = id;
3121
3122 BLI_addtail(new_lb, id_old);
3123 BLI_addtail(old_lb, id);
3124
3125 /* In case a library has been re-read, it has added already its own split main to the new Main
3126 * (see #direct_link_library code).
3127 *
3128 * Since we are replacing it with the 'id_old' address, we need to update that Main::curlib
3129 * pointer accordingly.
3130 *
3131 * Note that:
3132 * - This code is only for undo, and on undo we do not re-read regular libraries, only archive
3133 * ones for packed data.
3134 * - The new split main should still be empty at this stage (this code and adding the split
3135 * Main in #direct_link_library are part of the same #read_libblock call).
3136 */
3137 if (GS(id_old->name) == ID_LI) {
3138 Library *lib_old = blender::id_cast<Library *>(id_old);
3139 Library *lib = blender::id_cast<Library *>(id);
3141
3142 for (Main *bmain_iter : *fd->bmain->split_mains) {
3143 if (bmain_iter->curlib == lib) {
3144 BLI_assert(BKE_main_is_empty(bmain_iter));
3145 bmain_iter->curlib = lib_old;
3146 }
3147 }
3148 }
3149}
3150
3152 FileData *fd, Main *main, BHead *bhead, const int id_tag, ID **r_id_old)
3153{
3154 BLI_assert(fd->old_idmap_uid != nullptr);
3155
3156 /* Get pointer to memory of new ID that we will be reading. */
3157 const ID *id = static_cast<const ID *>(peek_struct_undo(fd, bhead));
3158 const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id);
3159
3160 const bool do_partial_undo = (fd->skip_flags & BLO_READ_SKIP_UNDO_OLD_MAIN) == 0;
3161#ifndef NDEBUG
3162 if (do_partial_undo && (bhead->code != ID_LINK_PLACEHOLDER) &&
3163 (blo_bhead_id_flag(fd, bhead) & ID_FLAG_LINKED_AND_PACKED) == 0)
3164 {
3165 /* This code should only ever be reached for local or packed data-blocks. */
3166 BLI_assert(main->curlib == nullptr);
3167 }
3168#endif
3169
3170 /* Find the 'current' existing ID we want to reuse instead of the one we
3171 * would read from the undo memfile. */
3172 ID *id_old = (fd->old_idmap_uid != nullptr) ?
3174 nullptr;
3175
3176 if (bhead->code == ID_LI) {
3177 /* Restore library datablock, if possible.
3178 *
3179 * Never handle archive libraries and their packed IDs as normal ones. These are local data,
3180 * and need to be fully handled like local IDs. */
3181 if (id_old && (reinterpret_cast<Library *>(id_old)->flag & LIBRARY_FLAG_IS_ARCHIVE) == 0 &&
3182 read_libblock_undo_restore_library(fd, id, id_old, bhead))
3183 {
3184 return true;
3185 }
3186 }
3187 else if (bhead->code == ID_LINK_PLACEHOLDER) {
3188 /* Restore linked datablock. */
3189 if (read_libblock_undo_restore_linked(fd, main, id, &id_old, bhead)) {
3190 return true;
3191 }
3192 }
3193 else if (id_type->flags & IDTYPE_FLAGS_NO_MEMFILE_UNDO) {
3194 CLOG_DEBUG(
3195 &LOG_UNDO, "UNDO: skip restore datablock %s, 'NO_MEMFILE_UNDO' type of ID", id->name);
3196
3197 /* If that local noundo ID still exists currently, the call to
3198 * #read_undo_reuse_noundo_local_ids at the beginning of #blo_read_file_internal will already
3199 * have moved it into the new main, and populated accordingly the new_idmap_uid.
3200 *
3201 * If this is the case, it can also be remapped for newly read data. Otherwise, this is 'lost'
3202 * data that cannot be restored on undo, so no remapping should exist for it in the ID
3203 * oldnewmap. */
3204 if (id_old) {
3205 BLI_assert(id_old ==
3206 static_cast<ID *>(BKE_main_idmap_lookup_uid(fd->new_idmap_uid, id->session_uid)));
3207 oldnewmap_lib_insert(fd, bhead->old, id_old, bhead->code);
3208 }
3209 return true;
3210 }
3211
3212 if (!do_partial_undo) {
3214 "UNDO: read %s (uid %u) -> no partial undo, always read at new address",
3215 id->name,
3216 id->session_uid);
3217 return false;
3218 }
3219
3220 /* Restore local datablocks. */
3221 if (id_old != nullptr && read_libblock_is_identical(fd, bhead)) {
3222 /* Local datablock was unchanged, restore from the old main. */
3224 "UNDO: read %s (uid %u) -> keep identical data-block",
3225 id->name,
3226 id->session_uid);
3227
3228 read_libblock_undo_restore_identical(fd, main, id, id_old, bhead, id_tag);
3229
3230 *r_id_old = id_old;
3231 return true;
3232 }
3233 if (id_old != nullptr) {
3234 /* Local datablock was changed. Restore at the address of the old datablock. */
3236 "UNDO: read %s (uid %u) -> read to old existing address",
3237 id->name,
3238 id->session_uid);
3239 *r_id_old = id_old;
3240 return false;
3241 }
3242
3243 /* Local datablock does not exist in the undo step, so read from scratch. */
3244 CLOG_DEBUG(
3245 &LOG_UNDO, "UNDO: read %s (uid %u) -> read at new address", id->name, id->session_uid);
3246 return false;
3247}
3248
3249/* This routine reads a datablock and its direct data, and advances bhead to
3250 * the next datablock. For library linked datablocks, only a placeholder will
3251 * be generated, to be replaced in read_library_linked_ids.
3252 *
3253 * When reading for undo, libraries, linked datablocks and unchanged datablocks
3254 * will be restored from the old database. Only new or changed datablocks will
3255 * actually be read. */
3257 Main *main,
3258 BHead *bhead,
3259 int id_tag,
3260 ID_Readfile_Data::Tags id_read_tags,
3261 const bool placeholder_set_indirect_extern,
3262 ID **r_id)
3263{
3264 const bool do_partial_undo = (fd->skip_flags & BLO_READ_SKIP_UNDO_OLD_MAIN) == 0;
3265
3266 /* First attempt to restore existing datablocks for undo.
3267 * When datablocks are changed but still exist, we restore them at the old
3268 * address and inherit recalc flags for the dependency graph. */
3269 ID *id_old = nullptr;
3270 if (fd->flags & FD_FLAGS_IS_MEMFILE) {
3271 if (read_libblock_undo_restore(fd, main, bhead, id_tag, &id_old)) {
3272 if (r_id) {
3273 *r_id = id_old;
3274 }
3275 if (main->id_map != nullptr && id_old != nullptr) {
3276 BKE_main_idmap_insert_id(main->id_map, id_old);
3277 }
3278
3279 return blo_bhead_next(fd, bhead);
3280 }
3281 }
3282
3283 /* Read libblock struct. */
3284 const int id_type_index = BKE_idtype_idcode_to_index(bhead->code);
3285#ifndef NDEBUG
3286 const char *blockname = nullptr;
3287#else
3288 /* Avoid looking up in the mapping for all read BHead, since this only contains the ID type name
3289 * in release builds. */
3290 const char *blockname = get_alloc_name(fd, bhead, nullptr, id_type_index);
3291#endif
3292 ID *id = read_id_struct(fd, bhead, blockname, id_type_index);
3293 if (id == nullptr) {
3294 if (r_id) {
3295 *r_id = nullptr;
3296 }
3297 return blo_bhead_next(fd, bhead);
3298 }
3299
3300 /* Determine ID type and add to main database list. */
3301 const short idcode = GS(id->name);
3302 ListBase *lb = which_libbase(main, idcode);
3303 if (lb == nullptr) {
3304 /* Unknown ID type. */
3305 CLOG_WARN(&LOG, "Unknown id code '%c%c'", (idcode & 0xff), (idcode >> 8));
3306 MEM_freeN(id);
3307 if (r_id) {
3308 *r_id = nullptr;
3309 }
3310 return blo_bhead_next(fd, bhead);
3311 }
3312
3313 /* NOTE: id must be added to the list before direct_link_id(), since
3314 * direct_link_library() may remove it from there in case of duplicates. */
3315 BLI_addtail(lb, id);
3316
3317 /* Insert into library map for lookup by newly read datablocks (with pointer value bhead->old).
3318 * Note that existing datablocks in memory (which pointer value would be id_old) are not remapped
3319 * remapped anymore, so no need to store this info here. */
3320 ID *id_target = (do_partial_undo && id_old != nullptr) ? id_old : id;
3321 oldnewmap_lib_insert(fd, bhead->old, id_target, bhead->code);
3322
3323 if (r_id) {
3324 *r_id = id_target;
3325 }
3326
3327 /* Set tag for new datablock to indicate lib linking and versioning needs
3328 * to be done still. */
3329 id_tag |= ID_TAG_NEW;
3330 id_read_tags.needs_linking = true;
3331
3332 if (bhead->code == ID_LINK_PLACEHOLDER) {
3333 /* Read placeholder for linked datablock. */
3334 id_read_tags.is_link_placeholder = true;
3335
3336 if (placeholder_set_indirect_extern) {
3337 if (id->flag & ID_FLAG_INDIRECT_WEAK_LINK) {
3338 id_tag |= ID_TAG_INDIRECT;
3339 }
3340 else {
3341 id_tag |= ID_TAG_EXTERN;
3342 }
3343 }
3344
3345 direct_link_id(fd, main, id_tag, id_read_tags, id, id_old);
3346
3347 if (main->id_map != nullptr) {
3348 BKE_main_idmap_insert_id(main->id_map, id);
3349 }
3350
3351 return blo_bhead_next(fd, bhead);
3352 }
3353
3354 /* Read datablock contents.
3355 * Use convenient malloc name for debugging and better memory link prints. */
3356 bhead = read_data_into_datamap(fd, bhead, blockname, id_type_index);
3357 const bool success = direct_link_id(fd, main, id_tag, id_read_tags, id, id_old);
3359
3360 if (!success) {
3361 /* XXX This is probably working OK currently given the very limited scope of that flag.
3362 * However, it is absolutely **not** handled correctly: it is freeing an ID pointer that has
3363 * been added to the fd->libmap mapping, which in theory could lead to nice crashes...
3364 * This should be properly solved at some point. */
3365 BKE_id_free(main, id);
3366 if (r_id != nullptr) {
3367 *r_id = nullptr;
3368 }
3369 }
3370 else {
3371 if (do_partial_undo && id_old != nullptr) {
3372 /* For undo, store contents read into id at id_old. */
3374 }
3375 if (fd->new_idmap_uid != nullptr) {
3377 }
3378 if (main->id_map != nullptr) {
3379 BKE_main_idmap_insert_id(main->id_map, id_target);
3380 }
3381 if (ID_IS_PACKED(id)) {
3382 BLI_assert(id->deep_hash != IDHash::get_null());
3383 fd->id_by_deep_hash->add_new(id->deep_hash, id);
3384 BLI_assert(main->curlib);
3385 }
3386 if (fd->file_stat) {
3387 id->runtime->src_blend_modifification_time = fd->file_stat->st_mtime;
3388 }
3389 }
3390
3391 return bhead;
3392}
3393
3395
3396/* -------------------------------------------------------------------- */
3399
3401{
3403
3404 bhead = read_data_into_datamap(fd, bhead, "Data for Asset meta-data", INDEX_ID_NULL);
3405
3406 BlendDataReader reader = {fd};
3407 BLO_read_struct(&reader, AssetMetaData, r_asset_data);
3408 BKE_asset_metadata_read(&reader, *r_asset_data);
3409
3411
3412 return bhead;
3413}
3414
3416
3417/* -------------------------------------------------------------------- */
3420
3421/* NOTE: this has to be kept for reading older files... */
3422/* also version info is written here */
3424{
3425 FileGlobal *fg = static_cast<FileGlobal *>(
3426 read_struct(fd, bhead, "Data from Global block", INDEX_ID_NULL));
3427
3428 /* NOTE: `bfd->main->versionfile` is supposed to have already been set from `fd->fileversion`
3429 * beforehand by calling code. */
3430 bfd->main->subversionfile = fg->subversion;
3433
3434 bfd->main->minversionfile = fg->minversion;
3436
3438 STRNCPY(bfd->main->build_hash, fg->build_hash);
3440
3444
3445 bfd->fileflags = fg->fileflags;
3446 bfd->globalf = fg->globalf;
3447
3448 /* NOTE: since 88b24bc6bb, `fg->filepath` is only written for crash recovery and autosave files,
3449 * so only overwrite `fd->relabase` if it is not empty, in case a regular blendfile is opened
3450 * through one of the 'recover' operators.
3451 *
3452 * In all other cases, the path is just set to the current path of the blendfile being read, so
3453 * there is no need to handle anymore older files (pre-2.65) that did not store (correctly) their
3454 * path. */
3455 if (G.fileflags & G_FILE_RECOVER_READ) {
3456 if (fg->filepath[0] != '\0') {
3457 STRNCPY(fd->relabase, fg->filepath);
3458 /* Used to set expected original filepath in read Main, instead of the path of the recovery
3459 * file itself. */
3460 STRNCPY(bfd->filepath, fg->filepath);
3461 }
3462 }
3463
3464 bfd->curscreen = fg->curscreen;
3465 bfd->curscene = fg->curscene;
3466 bfd->cur_view_layer = fg->cur_view_layer;
3467
3468 MEM_freeN(fg);
3469
3470 fd->globalf = bfd->globalf;
3471 fd->fileflags = bfd->fileflags;
3472
3473 return blo_bhead_next(fd, bhead);
3474}
3475
3476/* NOTE: this has to be kept for reading older files... */
3477static void link_global(FileData *fd, BlendFileData *bfd)
3478{
3479 bfd->cur_view_layer = static_cast<ViewLayer *>(
3481 bfd->curscreen = static_cast<bScreen *>(newlibadr(fd, nullptr, false, bfd->curscreen));
3482 bfd->curscene = static_cast<Scene *>(newlibadr(fd, nullptr, false, bfd->curscene));
3483 /* this happens in files older than 2.35 */
3484 if (bfd->curscene == nullptr) {
3485 if (bfd->curscreen) {
3486 bfd->curscene = bfd->curscreen->scene;
3487 }
3488 }
3489 if (bfd->curscene == nullptr) {
3490 bfd->curscene = static_cast<Scene *>(bfd->main->scenes.first);
3491 }
3492}
3493
3495
3496/* -------------------------------------------------------------------- */
3499
3500static void do_versions_userdef(FileData * /*fd*/, BlendFileData *bfd)
3501{
3502 UserDef *user = bfd->user;
3503
3504 if (user == nullptr) {
3505 return;
3506 }
3507
3509}
3510
3512{
3513 /* WATCH IT!!!: pointers from libdata have not been converted */
3514
3515 /* Don't allow versioning to create new data-blocks. */
3516 main->is_locked_for_linking = true;
3517
3518 /* Code ensuring conversion to/from new 'system IDProperties'. This needs to run before any other
3519 * data versioning. Otherwise, things like Cycles versioning code cannot work as expected. */
3520 if (!MAIN_VERSION_FILE_ATLEAST(main, 500, 27)) {
3521 /* Generate System IDProperties by copying the whole 'user-defined' historic IDProps into new
3522 * system-defined-only storage. While not optimal (as it also duplicates actual user-defined
3523 * IDProperties), this seems to be the only safe and sound way to handle the migration. */
3525 }
3526 if (!MAIN_VERSION_FILE_ATLEAST(main, 500, 70)) {
3527 /* Same as above, but decision to keep user-defined (aka custom properties) in nodes was taken
3528 * later during 5.0 development process. */
3530 }
3531 if (!MAIN_VERSION_FILE_ATLEAST(main, 500, 110)) {
3532 /* Same as above, but children bones were missed by initial versioning code, attempt to
3533 * transfer idprops data still in case they have no system properties defined yet. */
3535 }
3536
3537 if (G.debug & G_DEBUG) {
3538 char build_commit_datetime[32];
3539 time_t temp_time = main->build_commit_timestamp;
3540 tm *tm = (temp_time) ? gmtime(&temp_time) : nullptr;
3541 if (LIKELY(tm)) {
3542 strftime(build_commit_datetime, sizeof(build_commit_datetime), "%Y-%m-%d %H:%M", tm);
3543 }
3544 else {
3545 STRNCPY(build_commit_datetime, "unknown");
3546 }
3547
3548 CLOG_INFO(&LOG, "Read file %s", fd->relabase);
3549 CLOG_INFO(&LOG,
3550 " Version %d sub %d date %s hash %s",
3551 main->versionfile,
3552 main->subversionfile,
3553 build_commit_datetime,
3554 main->build_hash);
3555 }
3556
3557 if (!main->is_read_invalid) {
3559 }
3560 if (!main->is_read_invalid) {
3562 }
3563 if (!main->is_read_invalid) {
3565 }
3566 if (!main->is_read_invalid) {
3568 }
3569 if (!main->is_read_invalid) {
3571 }
3572 if (!main->is_read_invalid) {
3574 }
3575 if (!main->is_read_invalid) {
3577 }
3578 if (!main->is_read_invalid) {
3580 }
3581 if (!main->is_read_invalid) {
3583 }
3584 if (!main->is_read_invalid) {
3586 }
3587 if (!main->is_read_invalid) {
3589 }
3590 if (!main->is_read_invalid) {
3592 }
3593 if (!main->is_read_invalid) {
3595 }
3596 if (!main->is_read_invalid) {
3598 }
3599
3600 /* WATCH IT!!!: pointers from libdata have not been converted yet here! */
3601 /* WATCH IT 2!: #UserDef struct init see #do_versions_userdef() above! */
3602
3603 /* don't forget to set version number in BKE_blender_version.h! */
3604
3605 main->is_locked_for_linking = false;
3606}
3607
3609{
3610 BLI_assert(fd != nullptr);
3611
3612 CLOG_DEBUG(&LOG,
3613 "Processing %s (%s), %d.%d",
3614 main->curlib ? main->curlib->filepath : main->filepath,
3615 main->curlib ? "LIB" : "MAIN",
3616 main->versionfile,
3617 main->subversionfile);
3618
3619 /* Don't allow versioning to create new data-blocks. */
3620 main->is_locked_for_linking = true;
3621
3622 if (!main->is_read_invalid) {
3624 }
3625 if (!main->is_read_invalid) {
3627 }
3628 if (!main->is_read_invalid) {
3630 }
3631 if (!main->is_read_invalid) {
3633 }
3634 if (!main->is_read_invalid) {
3636 }
3637 if (!main->is_read_invalid) {
3639 }
3640 if (!main->is_read_invalid) {
3642 }
3643 if (!main->is_read_invalid) {
3645 }
3646 if (!main->is_read_invalid) {
3648 }
3649 if (!main->is_read_invalid) {
3651 }
3652 if (!main->is_read_invalid) {
3654 }
3655 if (!main->is_read_invalid) {
3657 }
3658 if (!main->is_read_invalid) {
3660 }
3661
3662 main->is_locked_for_linking = false;
3663}
3664
3666
3667/* -------------------------------------------------------------------- */
3670
3672{
3673 /* Embedded IDs are not known by lib_link code, so they would be remapped to `nullptr`. But there
3674 * is no need to process them anyway, as they are already handled during the 'read_data' phase.
3675 *
3676 * NOTE: Some external non-owning pointers to embedded IDs (like the node-tree pointers of the
3677 * Node editor) will not be detected as embedded ones though at 'lib_link' stage (because their
3678 * source data cannot be accessed). This is handled on a case-by-case basis in 'after_lib_link'
3679 * validation code. */
3681 return IDWALK_RET_NOP;
3682 }
3683
3684 /* Explicitly requested to be ignored during readfile processing. Means the read_data code
3685 * already handled this pointer. Typically, the 'owner_id' pointer of an embedded ID. */
3686 if (cb_data->cb_flag & IDWALK_CB_READFILE_IGNORE) {
3687 return IDWALK_RET_NOP;
3688 }
3689
3690 BlendLibReader *reader = static_cast<BlendLibReader *>(cb_data->user_data);
3691 ID **id_ptr = cb_data->id_pointer;
3692 ID *owner_id = cb_data->owner_id;
3693
3694 *id_ptr = BLO_read_get_new_id_address(reader, owner_id, ID_IS_LINKED(owner_id), *id_ptr);
3695
3696 return IDWALK_RET_NOP;
3697}
3698
3699static void lib_link_all(FileData *fd, Main *bmain)
3700{
3701 BlendLibReader reader = {fd, bmain};
3702
3703 ID *id;
3704 FOREACH_MAIN_ID_BEGIN (bmain, id) {
3705 const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id);
3706
3708 {
3710 /* This ID has been re-used from 'old' bmain. Since it was therefore unchanged across
3711 * current undo step, and old IDs re-use their old memory address, we do not need to liblink
3712 * it at all. */
3714
3715 /* Some data that should be persistent, like the 3DCursor or the tool settings, are
3716 * stored in IDs affected by undo, like Scene. So this requires some specific handling. */
3717 /* NOTE: even though the ID may have been detected as unchanged, the 'undo_preserve' may have
3718 * to actually change some of its ID pointers, it's e.g. the case with Scene's tool-settings
3719 * Brush/Palette pointers. This is the case where both new and old ID may be the same. */
3720 if (id_type->blend_read_undo_preserve != nullptr) {
3722 id_type->blend_read_undo_preserve(&reader, id, id->orig_id ? id->orig_id : id);
3723 }
3724 continue;
3725 }
3726
3728 /* Not all original pointer values can be considered as valid.
3729 * Handling of DNA deprecated data should never be needed in undo case. */
3731 ((fd->flags & FD_FLAGS_IS_MEMFILE) ?
3732 IDWALK_NOP :
3734 BKE_library_foreach_ID_link(bmain, id, lib_link_cb, &reader, flag);
3735
3736 after_liblink_id_process(&reader, id);
3737
3739 }
3740
3741 /* Some data that should be persistent, like the 3DCursor or the tool settings, are
3742 * stored in IDs affected by undo, like Scene. So this requires some specific handling. */
3743 if (id_type->blend_read_undo_preserve != nullptr && id->orig_id != nullptr) {
3745 id_type->blend_read_undo_preserve(&reader, id, id->orig_id);
3746 }
3747 }
3749
3750 /* Cleanup `ID.orig_id`, this is now reserved for depsgraph/copy-on-eval usage only. */
3751 FOREACH_MAIN_ID_BEGIN (bmain, id) {
3752 id->orig_id = nullptr;
3753 }
3755
3756#ifndef NDEBUG
3757 /* Double check we do not have any 'need link' tag remaining, this should never be the case once
3758 * this function has run. */
3759 FOREACH_MAIN_ID_BEGIN (bmain, id) {
3761 }
3763#endif
3764}
3765
3772{
3773 /* We only expect a merged Main here, not a split one. */
3774 BLI_assert(!bmain->split_mains);
3775
3776 if (!BKE_main_namemap_validate_and_fix(*bmain)) {
3777 BKE_report(
3778 reports ? reports->reports : nullptr,
3779 RPT_ERROR,
3780 "Critical blend-file corruption: Conflicts and/or otherwise invalid data-blocks names "
3781 "(see console for details)");
3782 }
3783
3784 /* Check for possible cycles in scenes' 'set' background property. */
3786
3787 /* We could integrate that to mesh/curve/lattice lib_link, but this is really cheap process,
3788 * so simpler to just use it directly in this single call. */
3789 BLO_main_validate_shapekeys(bmain, reports ? reports->reports : nullptr);
3790
3791 BLO_main_validate_embedded_flag(bmain, reports ? reports->reports : nullptr);
3792 BLO_main_validate_embedded_liboverrides(bmain, reports ? reports->reports : nullptr);
3793
3794 /* We have to rebuild that runtime information *after* all data-blocks have been properly linked.
3795 */
3797}
3798
3800
3801/* -------------------------------------------------------------------- */
3804
3806{
3807 BLO_read_struct(reader, IDProperty, &kmi->properties);
3808 IDP_BlendDataRead(reader, &kmi->properties);
3809 kmi->ptr = nullptr;
3810 kmi->flag &= ~KMI_UPDATE;
3811}
3812
3814{
3815 UserDef *user;
3816 bfd->user = user = static_cast<UserDef *>(
3817 read_struct(fd, bhead, "Data for User Def", INDEX_ID_NULL));
3818
3819 /* User struct has separate do-version handling */
3820 user->versionfile = bfd->main->versionfile;
3821 user->subversionfile = bfd->main->subversionfile;
3822
3823 /* read all data into fd->datamap */
3824 bhead = read_data_into_datamap(fd, bhead, "Data for User Def", INDEX_ID_NULL);
3825
3826 BlendDataReader reader_ = {fd};
3827 BlendDataReader *reader = &reader_;
3828
3829 BLO_read_struct_list(reader, bTheme, &user->themes);
3832 BLO_read_struct_list(reader, bUserMenu, &user->user_menus);
3833 BLO_read_struct_list(reader, bAddon, &user->addons);
3839
3840 LISTBASE_FOREACH (wmKeyMap *, keymap, &user->user_keymaps) {
3841 keymap->modal_items = nullptr;
3842 keymap->poll = nullptr;
3843 keymap->flag &= ~KEYMAP_UPDATE;
3844
3845 BLO_read_struct_list(reader, wmKeyMapDiffItem, &keymap->diff_items);
3846 BLO_read_struct_list(reader, wmKeyMapItem, &keymap->items);
3847
3848 LISTBASE_FOREACH (wmKeyMapDiffItem *, kmdi, &keymap->diff_items) {
3849 BLO_read_struct(reader, wmKeyMapItem, &kmdi->remove_item);
3850 BLO_read_struct(reader, wmKeyMapItem, &kmdi->add_item);
3851
3852 if (kmdi->remove_item) {
3853 direct_link_keymapitem(reader, kmdi->remove_item);
3854 }
3855 if (kmdi->add_item) {
3856 direct_link_keymapitem(reader, kmdi->add_item);
3857 }
3858 }
3859
3860 LISTBASE_FOREACH (wmKeyMapItem *, kmi, &keymap->items) {
3861 direct_link_keymapitem(reader, kmi);
3862 }
3863 }
3864
3866 BLO_read_struct(reader, IDProperty, &kpt->prop);
3867 IDP_BlendDataRead(reader, &kpt->prop);
3868 }
3869
3870 LISTBASE_FOREACH (bUserMenu *, um, &user->user_menus) {
3871 BLO_read_struct_list(reader, bUserMenuItem, &um->items);
3872 LISTBASE_FOREACH (bUserMenuItem *, umi, &um->items) {
3873 if (umi->type == USER_MENU_TYPE_OPERATOR) {
3874 bUserMenuItem_Op *umi_op = (bUserMenuItem_Op *)umi;
3875 BLO_read_struct(reader, IDProperty, &umi_op->prop);
3876 IDP_BlendDataRead(reader, &umi_op->prop);
3877 }
3878 }
3879 }
3880
3881 LISTBASE_FOREACH (bAddon *, addon, &user->addons) {
3882 BLO_read_struct(reader, IDProperty, &addon->prop);
3883 IDP_BlendDataRead(reader, &addon->prop);
3884 }
3885
3888 }
3889
3891 BKE_asset_catalog_path_list_blend_read_data(reader, shelf_settings->enabled_catalog_paths);
3892 }
3893
3894 /* XXX */
3895 user->uifonts.first = user->uifonts.last = nullptr;
3896
3897 BLO_read_struct_list(reader, uiStyle, &user->uistyles);
3898
3899 /* Don't read the active app template, use the default one. */
3900 user->app_template[0] = '\0';
3901
3902 /* Clear runtime data. */
3903 user->runtime.is_dirty = false;
3904 user->edit_studio_light = 0;
3905
3906 /* free fd->datamap again */
3908
3909 return bhead;
3910}
3911
3913
3914/* -------------------------------------------------------------------- */
3917
3919{
3921 return IDWALK_RET_NOP;
3922 }
3923
3924 IDNameLib_Map *new_idmap_uid = static_cast<IDNameLib_Map *>(cb_data->user_data);
3925 ID **id_pointer = cb_data->id_pointer;
3926 if (*id_pointer != nullptr) {
3927 *id_pointer = BKE_main_idmap_lookup_uid(new_idmap_uid, (*id_pointer)->session_uid);
3928 }
3929
3930 return IDWALK_RET_NOP;
3931}
3932
3933/* Remap 'no undo' ID usages to matching IDs in new main.
3934 *
3935 * 'no undo' IDs have simply be moved from old to new main so far. However, unlike the other
3936 * re-used IDs (the 'unchanged' ones), there is no guarantee that all the ID pointers they use are
3937 * still valid.
3938 *
3939 * This code performs a remapping based on the session_uid. */
3941{
3942 Main *new_bmain = fd->bmain;
3943 ID *id_iter;
3944 FOREACH_MAIN_ID_BEGIN (new_bmain, id_iter) {
3945 if (ID_IS_LINKED(id_iter)) {
3946 continue;
3947 }
3948 if ((id_iter->tag & ID_TAG_UNDO_OLD_ID_REUSED_NOUNDO) == 0) {
3949 continue;
3950 }
3951
3954 }
3956}
3957
3962static void blo_read_file_checks(Main *bmain)
3963{
3964#ifndef NDEBUG
3965 BLI_assert(!bmain->split_mains);
3966 BLI_assert(!bmain->is_read_invalid);
3967
3968 LISTBASE_FOREACH (wmWindowManager *, wm, &bmain->wm) {
3969 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
3970 /* This pointer is deprecated and should always be nullptr. */
3971 BLI_assert(win->screen == nullptr);
3972 }
3973 }
3974#endif
3975 UNUSED_VARS_NDEBUG(bmain);
3976}
3977
3979{
3980 BHead *bhead = blo_bhead_first(fd);
3981 BlendFileData *bfd;
3982
3983 const bool is_undo = (fd->flags & FD_FLAGS_IS_MEMFILE) != 0;
3984 if (is_undo) {
3985 CLOG_DEBUG(&LOG_UNDO, "UNDO: read step");
3986 }
3987
3988 /* Prevent any run of layer collections rebuild during readfile process, and the do_versions
3989 * calls.
3990 *
3991 * NOTE: Typically readfile code should not trigger such updates anyway. But some calls to
3992 * non-BLO functions (e.g. ID deletion) can indirectly trigger it. */
3994
3995 bfd = MEM_new<BlendFileData>(__func__);
3996
3997 bfd->main = BKE_main_new();
3998 bfd->main->versionfile = fd->fileversion;
3999 STRNCPY(bfd->filepath, filepath);
4000
4001 fd->bmain = bfd->main;
4002 fd->fd_bmain = bfd->main;
4003
4004 bfd->type = BLENFILETYPE_BLEND;
4005
4006 if ((fd->skip_flags & BLO_READ_SKIP_DATA) == 0) {
4007 blo_split_main(bfd->main);
4008 STRNCPY(bfd->main->filepath, filepath);
4009 }
4010
4011 if (G.background) {
4012 /* We only read & store .blend thumbnail in background mode
4013 * (because we cannot re-generate it, no OpenGL available).
4014 */
4015 const int *data = read_file_thumbnail(fd);
4016
4017 if (data) {
4018 const int width = data[0];
4019 const int height = data[1];
4020 if (BLEN_THUMB_MEMSIZE_IS_VALID(width, height)) {
4021 const size_t data_size = BLEN_THUMB_MEMSIZE(width, height);
4022 bfd->main->blen_thumb = static_cast<BlendThumbnail *>(MEM_mallocN(data_size, __func__));
4023
4024 BLI_assert((data_size - sizeof(*bfd->main->blen_thumb)) ==
4025 (BLEN_THUMB_MEMSIZE_FILE(width, height) - (sizeof(*data) * 2)));
4026 bfd->main->blen_thumb->width = width;
4027 bfd->main->blen_thumb->height = height;
4028 memcpy(bfd->main->blen_thumb->rect, &data[2], data_size - sizeof(*bfd->main->blen_thumb));
4029 }
4030 }
4031 }
4032
4033 if (is_undo) {
4034 /* This idmap will store UIDs of all IDs ending up in the new main, whether they are newly
4035 * read, or re-used from the old main. */
4037
4038 /* Copy all 'no undo' local data from old to new bmain. */
4040 }
4041
4042 while (bhead) {
4043 /* If not-null after the `switch`, the BHead is an ID one and needs to be read. */
4044 Main *bmain_to_read_into = nullptr;
4045 bool placeholder_set_indirect_extern = false;
4046
4047 switch (bhead->code) {
4048 case BLO_CODE_DATA:
4049 case BLO_CODE_DNA1:
4050 case BLO_CODE_TEST: /* used as preview since 2.5x */
4051 case BLO_CODE_REND:
4052 bhead = blo_bhead_next(fd, bhead);
4053 break;
4054 case BLO_CODE_GLOB:
4055 bhead = read_global(bfd, fd, bhead);
4056 break;
4057 case BLO_CODE_USER:
4059 bhead = blo_bhead_next(fd, bhead);
4060 }
4061 else {
4062 bhead = read_userdef(bfd, fd, bhead);
4063 }
4064 break;
4065 case BLO_CODE_ENDB:
4066 bhead = nullptr;
4067 break;
4068
4070 if ((fd->skip_flags & BLO_READ_SKIP_DATA) != 0) {
4071 bhead = blo_bhead_next(fd, bhead);
4072 break;
4073 }
4074 /* Add link placeholder to the main of the library it belongs to.
4075 *
4076 * The library is the most recently loaded #ID_LI block, according to the file format
4077 * definition. So we can use the entry at the end of `fd->bmain->split_mains`, typically
4078 * the one last added in #direct_link_library. */
4079 bmain_to_read_into = (*fd->bmain->split_mains)[fd->bmain->split_mains->size() - 1];
4080 placeholder_set_indirect_extern = true;
4081 break;
4082 case ID_LI:
4083 if ((fd->skip_flags & BLO_READ_SKIP_DATA) != 0) {
4084 bhead = blo_bhead_next(fd, bhead);
4085 break;
4086 }
4087 /* Library IDs are always read into the first (aka 'local') Main, even if they are written
4088 * in 'library' blendfile-space (for archive libraries e.g.). */
4089 bmain_to_read_into = fd->bmain;
4090 break;
4091 case ID_SCRN:
4092 /* in 2.50+ files, the file identifier for screens is patched, forward compatibility */
4093 bhead->code = ID_SCR;
4094 /* pass on to default */
4096 default: {
4097 if ((fd->skip_flags & BLO_READ_SKIP_DATA) != 0 || !blo_bhead_is_id_valid_type(bhead)) {
4098 bhead = blo_bhead_next(fd, bhead);
4099 break;
4100 }
4101 /* Put read real ID into the main of the library it belongs to.
4102 *
4103 * Local IDs should all be written before any Library in the blendfile, so this code will
4104 * always select `fd->bmain` for these.
4105 *
4106 * Packed linked IDs are real ID data in the currently read blendfile (unlike placeholders
4107 * for regular linked data). But they are in their archive library 'name space' and
4108 * 'blendfile space', so this follows the same logic as for placeholders to select the
4109 * Main.
4110 *
4111 * The library is the most recently loaded #ID_LI block, according to the file format
4112 * definition. So we can use the entry at the end of `fd->bmain->split_mains`, typically
4113 * the one last added in #direct_link_library. */
4114 bmain_to_read_into = (*fd->bmain->split_mains)[fd->bmain->split_mains->size() - 1];
4115 BLI_assert_msg((bmain_to_read_into == fd->bmain ||
4116 (blo_bhead_id_flag(fd, bhead) & ID_FLAG_LINKED_AND_PACKED) != 0),
4117 "Local IDs should always be put in the first Main split data-base, not in "
4118 "a 'linked data' one");
4119 }
4120 }
4121 if (bmain_to_read_into) {
4122 bhead = read_libblock(
4123 fd, bmain_to_read_into, bhead, 0, {}, placeholder_set_indirect_extern, nullptr);
4124 }
4125
4126 if (bfd->main->is_read_invalid) {
4127 return bfd;
4128 }
4129 }
4130
4131 if (is_undo) {
4132 /* Move the remaining Library IDs and their linked data to the new main.
4133 *
4134 * NOTE: These linked IDs have not been detected as used in newly read main. However, they
4135 * could be dependencies from some 'no undo' IDs that were unconditionally moved from the old
4136 * to the new main.
4137 *
4138 * While there could be some more refined check here to detect such cases and only move these
4139 * into the new bmain, in practice it is simpler to systematically move all linked data. The
4140 * handling of libraries already moves all their linked IDs too, regardless of whether they are
4141 * effectively used or not. */
4142
4143 Main *old_main = fd->old_bmain;
4144 BLI_assert(old_main != nullptr);
4145 BLI_assert(old_main->curlib == nullptr);
4146 BLI_assert(old_main->split_mains);
4147 /* Cannot iterate directly over `old_main->split_mains`, as this is likely going to remove some
4148 * of its items. */
4149 blender::Vector<Main *> old_main_split_mains = {old_main->split_mains->as_span()};
4150 for (Main *libmain : old_main_split_mains.as_span().drop_front(1)) {
4151 BLI_assert(libmain->curlib);
4152 if (libmain->curlib->flag & LIBRARY_FLAG_IS_ARCHIVE) {
4153 /* Never move archived libraries and their content, these are 'local' data in undo context,
4154 * so all packed linked IDs should have been handled like local ones undo-wise, and if
4155 * packed libraries remain unused at this point, then they are indeed fully unused/removed
4156 * from the new main. */
4157 continue;
4158 }
4159 read_undo_move_libmain_data(fd, libmain, nullptr);
4160 }
4161 }
4162
4163 /* Ensure fully valid and unique ID names before calling first stage of versioning. */
4164 if (!is_undo && (fd->flags & FD_FLAGS_HAS_INVALID_ID_NAMES) != 0) {
4166
4170 "Blendfile '%s' was created by a future version of Blender and contains ID "
4171 "names longer than currently supported. These have been truncated.",
4172 bfd->filepath);
4173 }
4174 else {
4176 RPT_ERROR,
4177 "Blendfile '%s' appears corrupted, it contains invalid ID names. These have "
4178 "been truncated.",
4179 bfd->filepath);
4180 }
4181
4182 /* This part is only to ensure forward compatibility with 5.0+ blend-files in 4.5.
4183 * It will be removed in 5.0. */
4185 }
4186 else {
4187 /* Getting invalid ID names from memfile undo data would be a critical error. */
4189 if ((fd->flags & FD_FLAGS_HAS_INVALID_ID_NAMES) != 0) {
4190 bfd->main->is_read_invalid = true;
4191 }
4192 }
4193
4194 if (bfd->main->is_read_invalid) {
4195 return bfd;
4196 }
4197
4198 /* Do versioning before read_libraries, but skip in undo case. */
4199 if (!is_undo) {
4200 if ((fd->skip_flags & BLO_READ_SKIP_DATA) == 0) {
4201 for (Main *bmain : *fd->bmain->split_mains) {
4202 /* Packed IDs are stored in the current .blend file, but belong to dedicated 'archive
4203 * library' Mains, not the first, 'local' Main. So they do need versioning here, as for
4204 * local IDs, which is why all the split Mains in the list need to be checked.
4205 *
4206 * Placeholders (of 'real' linked data) can't be versioned yet. Since they also belong to
4207 * dedicated 'library' Mains, and are not mixed with the 'packed' ones, these Mains can be
4208 * entirely skipped. */
4209 const bool contains_link_placeholder = (bmain->curlib != nullptr &&
4210 (bmain->curlib->flag & LIBRARY_FLAG_IS_ARCHIVE) ==
4211 0);
4212#ifndef NDEBUG
4213 MainListsArray lbarray = BKE_main_lists_get(*bmain);
4214 for (ListBase *lb_array : lbarray) {
4215 LISTBASE_FOREACH_MUTABLE (ID *, id, lb_array) {
4216 BLI_assert_msg((id->runtime->readfile_data->tags.is_link_placeholder ==
4217 contains_link_placeholder),
4218 contains_link_placeholder ?
4219 "Real Library split Main contains non-placeholder IDs" :
4220 (bmain->curlib == nullptr ?
4221 "Local data split Main contains placeholder IDs" :
4222 "Archive Library split Main contains placeholder IDs"));
4223 }
4224 }
4225#endif
4226 if (contains_link_placeholder) {
4227 continue;
4228 }
4229 do_versions(fd, bmain->curlib, bmain);
4230 }
4231 }
4232
4233 if ((fd->skip_flags & BLO_READ_SKIP_USERDEF) == 0) {
4234 do_versions_userdef(fd, bfd);
4235 }
4236 }
4237
4238 if (bfd->main->is_read_invalid) {
4239 return bfd;
4240 }
4241
4242 if ((fd->skip_flags & BLO_READ_SKIP_DATA) == 0) {
4244 read_libraries(fd);
4245 BLI_assert((*bfd->main->split_mains)[0] == bfd->main);
4246 blo_join_main(bfd->main);
4247
4248 lib_link_all(fd, bfd->main);
4250
4251 if (is_undo) {
4252 /* Ensure ID usages of reused 'no undo' IDs remain valid. */
4253 /* Although noundo data was reused as-is from the old main, it may have ID pointers to data
4254 * that has been removed, or that have a new address. */
4256 }
4257
4259
4260 /* Skip in undo case. */
4261 if (!is_undo) {
4262 /* Note that we can't recompute user-counts at this point in undo case, we play too much with
4263 * IDs from different memory realms, and Main database is not in a fully valid state yet.
4264 */
4265 /* Some versioning code does expect some proper user-reference-counting, e.g. in conversion
4266 * from groups to collections... We could optimize out that first call when we are reading a
4267 * current version file, but again this is really not a bottle neck currently.
4268 * So not worth it. */
4270
4271 /* Necessary to allow 2.80 layer collections conversion code to work. */
4273
4274 /* Yep, second splitting... but this is a very cheap operation, so no big deal. */
4275 blo_split_main(bfd->main);
4276 for (Main *mainvar : *bfd->main->split_mains) {
4277 /* Do versioning for newly added linked data-blocks. If no data-blocks were read from a
4278 * library versionfile will still be zero and we can skip it. */
4279 if (mainvar->versionfile == 0) {
4280 continue;
4281 }
4282 do_versions_after_linking((mainvar->curlib && mainvar->curlib->runtime->filedata) ?
4283 mainvar->curlib->runtime->filedata :
4284 fd,
4285 mainvar);
4287 }
4288 blo_join_main(bfd->main);
4289
4291
4292 /* And we have to compute those user-reference-counts again, as `do_versions_after_linking()`
4293 * does not always properly handle user counts, and/or that function does not take into
4294 * account old, deprecated data. */
4296 }
4297
4299 /* Now we can clear this runtime library filedata, it is not needed anymore.
4300 *
4301 * NOTE: This is also important to do for archive libraries. */
4303 /* If no data-blocks were read from a library (should only happen when all references to a
4304 * library's data are `ID_FLAG_INDIRECT_WEAK_LINK`), its versionfile will still be zero and
4305 * it can be deleted.
4306 *
4307 * NOTES:
4308 * - In case the library blendfile exists but is missing all the referenced linked IDs, the
4309 * placeholders IDs created will reference the library ID, and the library ID will have a
4310 * valid version number as the file was read to search for the linked IDs.
4311 * - In case the library blendfile does not exist, its local Library ID will get the version
4312 * of the current local Main (i.e. the loaded blendfile).
4313 * - In case it is a reference library for archived ones, its runtime #archived_libraries
4314 * vector will not be empty, and it must be kept, even if no data is directly linked from
4315 * it anymore.
4316 */
4317 if (lib->runtime->versionfile == 0 && lib->runtime->archived_libraries.is_empty()) {
4318#ifndef NDEBUG
4319 ID *id_iter;
4320 FOREACH_MAIN_ID_BEGIN (bfd->main, id_iter) {
4321 BLI_assert(id_iter->lib != lib);
4322 }
4324#endif
4325 BKE_id_delete(bfd->main, lib);
4326 }
4327 }
4328
4329 if (bfd->main->is_read_invalid) {
4330 return bfd;
4331 }
4332
4333 /* After all data has been read and versioned, uses ID_TAG_NEW. Theoretically this should
4334 * not be calculated in the undo case, but it is currently needed even on undo to recalculate
4335 * a cache. */
4337
4339
4340 BKE_main_id_tag_all(bfd->main, ID_TAG_NEW, false);
4341
4342 /* Must happen before applying liboverrides, as this process may fully invalidate e.g. view
4343 * layer pointers in case a Scene is a liboverride. */
4344 link_global(fd, bfd);
4345
4346 /* Now that all our data-blocks are loaded,
4347 * we can re-generate overrides from their references. */
4348 if (!is_undo) {
4349 /* Do not apply in undo case! */
4351
4352 std::string cur_view_layer_name = bfd->cur_view_layer != nullptr ?
4353 bfd->cur_view_layer->name :
4354 "";
4355
4358
4359 /* In case the current scene is a liboverride, while the ID pointer itself remains valid,
4360 * above update of liboverrides will have completely invalidated its old content, so the
4361 * current view-layer needs to be searched for again. */
4362 if (bfd->cur_view_layer != nullptr) {
4363 bfd->cur_view_layer = BKE_view_layer_find(bfd->curscene, cur_view_layer_name.c_str());
4364 }
4365
4366 /* FIXME Temporary 'fix' to a problem in how temp ID are copied in
4367 * `BKE_lib_override_library_main_update`, see #103062.
4368 * Proper fix involves first addressing #90610. */
4370
4371 /* Update invariants after re-generating overrides. */
4373
4376 }
4377
4379
4381
4382 /* Make all relative paths, relative to the open blend file. */
4384 }
4385 else {
4387 }
4388
4389 BLI_assert(!bfd->main->split_mains);
4390 BLI_assert(bfd->main->id_map == nullptr);
4391
4392 /* Sanity checks. */
4394
4395 return bfd;
4396}
4397
4399
4400/* -------------------------------------------------------------------- */
4405
4408 const void *old;
4409};
4410
4411static int verg_bheadsort(const void *v1, const void *v2)
4412{
4413 const BHeadSort *x1 = static_cast<const BHeadSort *>(v1),
4414 *x2 = static_cast<const BHeadSort *>(v2);
4415
4416 if (x1->old > x2->old) {
4417 return 1;
4418 }
4419 if (x1->old < x2->old) {
4420 return -1;
4421 }
4422 return 0;
4423}
4424
4426{
4427 BHead *bhead;
4428 BHeadSort *bhs;
4429 int tot = 0;
4430
4431 for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
4432 tot++;
4433 }
4434
4435 fd->tot_bheadmap = tot;
4436 if (tot == 0) {
4437 return;
4438 }
4439
4440 bhs = fd->bheadmap = MEM_malloc_arrayN<BHeadSort>(tot, "BHeadSort");
4441
4442 for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead), bhs++) {
4443 bhs->bhead = bhead;
4444 bhs->old = bhead->old;
4445 }
4446
4447 qsort(fd->bheadmap, tot, sizeof(BHeadSort), verg_bheadsort);
4448}
4449
4451{
4452 /* Skip library data-blocks in undo, see comment in read_libblock. */
4453 if (fd->flags & FD_FLAGS_IS_MEMFILE) {
4454 return nullptr;
4455 }
4456
4457 for (; bhead; bhead = blo_bhead_prev(fd, bhead)) {
4458 if (bhead->code == ID_LI) {
4459 break;
4460 }
4461 }
4462
4463 return bhead;
4464}
4465
4466static BHead *find_bhead(FileData *fd, void *old)
4467{
4468#if 0
4469 BHead *bhead;
4470#endif
4471 BHeadSort *bhs, bhs_s;
4472
4473 if (!old) {
4474 return nullptr;
4475 }
4476
4477 if (fd->bheadmap == nullptr) {
4479 }
4480
4481 bhs_s.old = old;
4482 bhs = static_cast<BHeadSort *>(
4483 bsearch(&bhs_s, fd->bheadmap, fd->tot_bheadmap, sizeof(BHeadSort), verg_bheadsort));
4484
4485 if (bhs) {
4486 return bhs->bhead;
4487 }
4488
4489#if 0
4490 for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
4491 if (bhead->old == old) {
4492 return bhead;
4493 }
4494 }
4495#endif
4496
4497 return nullptr;
4498}
4499
4500static BHead *find_bhead_from_code_name(FileData *fd, const short idcode, const char *name)
4501{
4502 char idname_full[MAX_ID_NAME];
4503 *((short *)idname_full) = idcode;
4504 BLI_strncpy(idname_full + 2, name, sizeof(idname_full) - 2);
4505
4506 return fd->bhead_idname_map->lookup_default(idname_full, nullptr);
4507}
4508
4509static BHead *find_bhead_from_idname(FileData *fd, const char *idname)
4510{
4511 BHead *bhead = fd->bhead_idname_map->lookup_default(idname, nullptr);
4512 if (LIKELY(bhead)) {
4513 return bhead;
4514 }
4515
4516 /* Expected ID was not found, attempt to load the same name, but for an older, deprecated and
4517 * converted ID type. */
4518 const short id_code_old = do_versions_new_to_old_idcode_get(GS(idname));
4519 if (id_code_old == ID_LINK_PLACEHOLDER) {
4520 return bhead;
4521 }
4522 return find_bhead_from_code_name(fd, id_code_old, idname + 2);
4523}
4524
4526{
4527 if (const IDHash *deep_hash = blo_bhead_id_deep_hash(fd, bhead)) {
4528 if (ID *existing_id = fd->id_by_deep_hash->lookup_default(*deep_hash, nullptr)) {
4529 return existing_id;
4530 }
4531 }
4532 return nullptr;
4533}
4534
4535static ID *library_id_is_yet_read_main(Main *mainvar, const char *idname)
4536{
4537 if (mainvar->id_map == nullptr) {
4538 mainvar->id_map = BKE_main_idmap_create(mainvar, false, nullptr, MAIN_IDMAP_TYPE_NAME);
4539 }
4540 BLI_assert(BKE_main_idmap_main_get(mainvar->id_map) == mainvar);
4541
4542 ID *existing_id = BKE_main_idmap_lookup_name(
4543 mainvar->id_map, GS(idname), idname + 2, mainvar->curlib);
4544 BLI_assert(existing_id ==
4545 BLI_findstring(which_libbase(mainvar, GS(idname)), idname, offsetof(ID, name)));
4546 return existing_id;
4547}
4548
4549static ID *library_id_is_yet_read(FileData *fd, Main *mainvar, BHead *bhead)
4550{
4551 if (ID *existing_id = library_id_is_yet_read_deep_hash(fd, bhead)) {
4552 return existing_id;
4553 }
4554
4555 const char *idname = blo_bhead_id_name(fd, bhead);
4556 if (!idname) {
4557 return nullptr;
4558 }
4559 return library_id_is_yet_read_main(mainvar, idname);
4560}
4561
4563 ReportList *reports,
4564 const bool has_forward_compatibility_issues,
4565 const char *filepath)
4566{
4567 if (!fd || (fd->flags & FD_FLAGS_HAS_INVALID_ID_NAMES) == 0) {
4568 return;
4569 }
4570 if (has_forward_compatibility_issues) {
4571 BKE_reportf(reports,
4573 "Library '%s' was created by a future version of Blender and contains ID names "
4574 "longer than currently supported. This may cause missing linked data, consider "
4575 "opening and re-saving that library with the current Blender version.",
4576 filepath);
4577 }
4578 else {
4579 BKE_reportf(reports,
4580 RPT_ERROR,
4581 "Library '%s' appears corrupted, it contains invalid ID names. This may cause "
4582 "missing linked data.",
4583 filepath);
4584 }
4585}
4586
4588
4589/* -------------------------------------------------------------------- */
4592
4593using BLOExpandDoitCallback = void (*)(void *fdhandle,
4594 std::queue<ID *> &ids_to_expand,
4595 Main *mainvar,
4596 void *idv);
4597
4604
4605/* Find the existing Main matching the given blendfile library filepath, or create a new one (with
4606 * the matching Library ID) if needed.
4607 *
4608 * NOTE: The process is a bit more complex for packed linked IDs and their archive libraries, as
4609 * in this case, this function also needs to find or create a new suitable archive library, i.e.
4610 * one which does not contain yet the given ID (from its name & type). */
4612 const char *lib_filepath,
4613 const char *relabase,
4614 const BHead *id_bhead,
4615 const char *id_name,
4616 const bool is_packed_id)
4617{
4618 Library *parent_lib = nullptr;
4619 char filepath_abs[FILE_MAX];
4620
4621 STRNCPY(filepath_abs, lib_filepath);
4622 BLI_path_abs(filepath_abs, relabase);
4623 BLI_path_normalize(filepath_abs);
4624
4625 for (Main *main_it : *fd->bmain->split_mains) {
4626 const char *libname = (main_it->curlib) ? main_it->curlib->runtime->filepath_abs :
4627 main_it->filepath;
4628
4629 if (BLI_path_cmp(filepath_abs, libname) == 0) {
4630 CLOG_DEBUG(&LOG,
4631 "Found library '%s' for file path '%s'",
4632 main_it->curlib ? main_it->curlib->id.name : "<None>",
4633 lib_filepath);
4634 /* Due to how parent and archive libraries are created and written in the blend-file,
4635 * the first library matching a given filepath should never be an archive one. */
4636 BLI_assert(!main_it->curlib || (main_it->curlib->flag & LIBRARY_FLAG_IS_ARCHIVE) == 0);
4637 if (!is_packed_id) {
4638 return main_it;
4639 }
4640 /* For packed IDs, the Main of the main owner library is not a valid one. Another loop is
4641 * needed into all the Mains matching the archive libraries of this main library. */
4642 BLI_assert(main_it->curlib);
4643 parent_lib = main_it->curlib;
4644 break;
4645 }
4646 }
4647
4648 if (is_packed_id) {
4649 if (parent_lib) {
4650 /* Try to find an 'available' existing archive Main library, i.e. one that does not yet
4651 * contain an ID of the same type and name. */
4652 for (Main *main_it : *fd->bmain->split_mains) {
4653 if (!main_it->curlib || (main_it->curlib->flag & LIBRARY_FLAG_IS_ARCHIVE) == 0 ||
4654 main_it->curlib->archive_parent_library != parent_lib)
4655 {
4656 continue;
4657 }
4658 if (ID *packed_id = library_id_is_yet_read_main(main_it, id_name)) {
4659 /* Archive Main library already contains a 'same' ID - but it should have a different
4660 * deep_hash. Otherwise, a previous call to `library_id_is_yet_read()` should have
4661 * returned this ID, and this code should not be reached. */
4662 BLI_assert(packed_id->deep_hash != *blo_bhead_id_deep_hash(fd, id_bhead));
4663 UNUSED_VARS_NDEBUG(packed_id, id_bhead);
4664 continue;
4665 }
4666 BLI_assert(ELEM(main_it->curlib->runtime->filedata, fd, nullptr));
4667 main_it->curlib->runtime->filedata = fd;
4668 main_it->curlib->runtime->is_filedata_owner = false;
4669 BLI_assert(main_it->versionfile != 0);
4670 CLOG_DEBUG(&LOG,
4671 "Found archive library '%s' for the packed ID '%s'",
4672 main_it->curlib->id.name,
4673 id_name);
4674 return main_it;
4675 }
4676 }
4677 else {
4678 /* An archive library requires an existing parent library, create an empty, 'virtual' one if
4679 * needed. */
4680 Main *reference_bmain = blo_add_main_for_library(
4681 fd, nullptr, nullptr, lib_filepath, filepath_abs, false);
4682 parent_lib = reference_bmain->curlib;
4683 CLOG_DEBUG(&LOG,
4684 "Added new parent library '%s' for file path '%s'",
4685 parent_lib->id.name,
4686 lib_filepath);
4687 }
4688 }
4689 BLI_assert(parent_lib || !is_packed_id);
4690
4692 fd, nullptr, parent_lib, lib_filepath, filepath_abs, is_packed_id);
4693
4695
4696 if (is_packed_id) {
4697 CLOG_DEBUG(&LOG,
4698 "Added new archive library '%s' for the packed ID '%s'",
4699 bmain->curlib->id.name,
4700 id_name);
4701 }
4702 else {
4703 CLOG_DEBUG(
4704 &LOG, "Added new library '%s' for file path '%s'", bmain->curlib->id.name, lib_filepath);
4705 }
4706 return bmain;
4707}
4708
4709/* Actually load an ID from a library. There are three possible cases here:
4710 * - `existing_id` is non-null: calling code already found a suitable existing ID, this function
4711 * essentially then only updates the mappings for `bhead->old` address to point to the given
4712 * ID. This is the only case where `libmain` may be `nullptr`.
4713 * - The given bhead has an already loaded matching ID (found by a call to
4714 * `library_id_is_yet_read`), then once that ID is found behavior is as in the previous case.
4715 * - No matching existing ID is found, then a new one is actually read from the given FileData.
4716 */
4717static void read_id_in_lib(FileData *fd,
4718 std::queue<ID *> &ids_to_expand,
4719 Main *libmain,
4720 Library *parent_lib,
4721 BHead *bhead,
4722 ID *existing_id,
4723 ID_Readfile_Data::Tags id_read_tags)
4724{
4725 ID *id = existing_id;
4726
4727 if (id == nullptr) {
4728 BLI_assert(libmain);
4729 id = library_id_is_yet_read(fd, libmain, bhead);
4730 }
4731 if (id == nullptr) {
4732 /* ID has not been read yet, add placeholder to the main of the
4733 * library it belongs to, so that it will be read later. */
4735 fd, libmain, bhead, fd->id_tag_extra | ID_TAG_INDIRECT, id_read_tags, false, &id);
4736 BLI_assert(id != nullptr);
4737 id_sort_by_name(which_libbase(libmain, GS(id->name)), id, static_cast<ID *>(id->prev));
4738
4739 /* commented because this can print way too much */
4740 // if (G.debug & G_DEBUG) printf("expand_doit: other lib %s\n", lib->filepath);
4741
4742 /* For outliner dependency only. */
4743 if (parent_lib) {
4744 libmain->curlib->runtime->parent = parent_lib;
4745 }
4746
4747 /* Only newly read ID needs to be added to the expand TODO queue, existing ones should already
4748 * be in it - or already have been expanded. */
4749 if (id_read_tags.needs_expanding) {
4750 ids_to_expand.push(id);
4751 }
4752 }
4753 else {
4754 /* Convert any previously read weak link to regular link to signal that we want to read this
4755 * data-block.
4756 *
4757 * Note that this function also visits already-loaded data-blocks, and thus their
4758 * `readfile_data` field might already have been freed. */
4760 id->flag &= ~ID_FLAG_INDIRECT_WEAK_LINK;
4761 }
4762
4763 /* "id" is either a placeholder or real ID that is already in the
4764 * main of the library (A) it belongs to. However it might have been
4765 * put there by another library (C) which only updated its own
4766 * fd->libmap. In that case we also need to update the fd->libmap
4767 * of the current library (B) so we can find it for lookups.
4768 *
4769 * An example of such a setup is:
4770 * (A) tree.blend: contains Tree object.
4771 * (B) forest.blend: contains Forest collection linking in Tree from tree.blend.
4772 * (C) shot.blend: links in both Tree from tree.blend and Forest from forest.blend.
4773 */
4774 oldnewmap_lib_insert(fd, bhead->old, id, bhead->code);
4775
4776 /* Commented because this can print way too much. */
4777#if 0
4778 if (G.debug & G_DEBUG) {
4779 printf("expand_doit: already linked: %s lib: %s\n", id->name, lib->filepath);
4780 }
4781#endif
4782 }
4783}
4784
4785static void expand_doit_library(void *fdhandle,
4786 std::queue<ID *> &ids_to_expand,
4787 Main *mainvar,
4788 void *old)
4789{
4790 FileData *fd = static_cast<FileData *>(fdhandle);
4791
4792 if (mainvar->is_read_invalid) {
4793 return;
4794 }
4795
4796 BHead *bhead = find_bhead(fd, old);
4797 if (bhead == nullptr) {
4798 return;
4799 }
4800 /* In 2.50+ file identifier for screens is patched, forward compatibility. */
4801 if (bhead->code == ID_SCRN) {
4802 bhead->code = ID_SCR;
4803 }
4804 if (!blo_bhead_is_id_valid_type(bhead)) {
4805 return;
4806 }
4807 const char *id_name = blo_bhead_id_name(fd, bhead);
4808 if (!id_name) {
4809 /* Do not allow linking ID which names are invalid (likely coming from a future version of
4810 * Blender allowing longer names). */
4811 return;
4812 }
4813 const bool is_packed_id = (blo_bhead_id_flag(fd, bhead) & ID_FLAG_LINKED_AND_PACKED) != 0;
4814
4815 BLI_assert_msg(!is_packed_id || bhead->code != ID_LINK_PLACEHOLDER,
4816 "A link placeholder ID (aka reference to some ID linked from another library) "
4817 "should never be packed.");
4818
4819 if (bhead->code == ID_LINK_PLACEHOLDER) {
4820 /* Placeholder link to data-block in another library. */
4821 BHead *bheadlib = find_previous_lib(fd, bhead);
4822 if (bheadlib == nullptr) {
4824 RPT_ERROR,
4825 RPT_("LIB: .blend file %s seems corrupted, no owner 'Library' data found "
4826 "for the linked data-block '%s'. Try saving the file again."),
4827 mainvar->curlib->runtime->filepath_abs,
4828 id_name ? id_name : "<InvalidIDName>");
4829 return;
4830 }
4831
4832 Library *lib = reinterpret_cast<Library *>(
4833 read_id_struct(fd, bheadlib, "Data for Library ID type", INDEX_ID_NULL));
4835 fd, lib->filepath, fd->relabase, nullptr, nullptr, false);
4836 MEM_freeN(lib);
4837
4838 if (libmain->curlib == nullptr) {
4841 RPT_("LIB: Data refers to main .blend file: '%s' from %s"),
4842 id_name ? id_name : "<InvalidIDName>",
4843 mainvar->curlib->runtime->filepath_abs);
4844 return;
4845 }
4846
4847 /* Placeholders never need expanding, as they are a mere reference to ID from another
4848 * library/blendfile. */
4849 read_id_in_lib(fd, ids_to_expand, libmain, mainvar->curlib, bhead, nullptr, {});
4850 }
4851 else if (is_packed_id) {
4852 /* Packed data-block from another library. */
4853
4854 /* That exact same packed ID may have already been read before. */
4855 if (ID *existing_id = library_id_is_yet_read_deep_hash(fd, bhead)) {
4856 /* Ensure that the current BHead's `old` pointer will also be remapped to the found existing
4857 * ID. */
4858 read_id_in_lib(fd, ids_to_expand, nullptr, nullptr, bhead, existing_id, {});
4859 return;
4860 }
4861
4862 BHead *bheadlib = find_previous_lib(fd, bhead);
4863 if (bheadlib == nullptr) {
4865 RPT_ERROR,
4866 RPT_("LIB: .blend file %s seems corrupted, no owner 'Library' data found "
4867 "for the packed linked data-block %s. Try saving the file again."),
4868 mainvar->curlib->runtime->filepath_abs,
4869 id_name ? id_name : "<InvalidIDName>");
4870 return;
4871 }
4872
4873 Library *lib = reinterpret_cast<Library *>(
4874 read_id_struct(fd, bheadlib, "Data for Library ID type", INDEX_ID_NULL));
4876 fd, lib->filepath, fd->relabase, bhead, id_name, is_packed_id);
4877 MEM_freeN(lib);
4878
4879 if (libmain->curlib == nullptr) {
4882 RPT_("LIB: Data refers to main .blend file: '%s' from %s"),
4883 id_name ? id_name : "<InvalidIDName>",
4884 mainvar->curlib->runtime->filepath_abs);
4885 return;
4886 }
4887
4888 ID_Readfile_Data::Tags id_read_tags{};
4889 id_read_tags.needs_expanding = true;
4890 read_id_in_lib(fd, ids_to_expand, libmain, nullptr, bhead, nullptr, id_read_tags);
4891 }
4892 else {
4893 /* Data-block in same library. */
4894 ID_Readfile_Data::Tags id_read_tags{};
4895 id_read_tags.needs_expanding = true;
4896 read_id_in_lib(fd, ids_to_expand, mainvar, nullptr, bhead, nullptr, id_read_tags);
4897 }
4898}
4899
4901{
4902 /* Embedded IDs are not known by lib_link code, so they would be remapped to `nullptr`. But there
4903 * is no need to process them anyway, as they are already handled during the 'read_data' phase.
4904 */
4906 return IDWALK_RET_NOP;
4907 }
4908
4909 /* Do not expand weak links. These are used when the user interface links to scene data,
4910 * but we don't want to bring along such datablocks with a workspace. */
4911 if (cb_data->cb_flag & IDWALK_CB_DIRECT_WEAK_LINK) {
4912 return IDWALK_RET_NOP;
4913 }
4914
4915 /* Explicitly requested to be ignored during readfile processing. Means the read_data code
4916 * already handled this pointer. Typically, the 'owner_id' pointer of an embedded ID. */
4917 if (cb_data->cb_flag & IDWALK_CB_READFILE_IGNORE) {
4918 return IDWALK_RET_NOP;
4919 }
4920
4921 /* Expand process can be re-entrant or have other complex interactions that will not work well
4922 * with loop-back pointers. Further more, processing such data should not be needed here anyway.
4923 */
4924 if (cb_data->cb_flag & (IDWALK_CB_LOOPBACK)) {
4925 return IDWALK_RET_NOP;
4926 }
4927
4928 BlendExpander *expander = static_cast<BlendExpander *>(cb_data->user_data);
4929 ID *id = *(cb_data->id_pointer);
4930
4931 if (id) {
4932 expander->callback(expander->fd, expander->ids_to_expand, expander->main, id);
4933 }
4934
4935 return IDWALK_RET_NOP;
4936}
4937
4938static void expand_main(void *fdhandle, Main *mainvar, BLOExpandDoitCallback callback)
4939{
4940 FileData *fd = static_cast<FileData *>(fdhandle);
4941 BlendExpander expander = {fd, {}, mainvar, callback};
4942
4943 /* Note: Packed IDs are the only current case where IDs read/loaded from a library blendfile will
4944 * end up in another Main (outside of placeholders, which never need to be expanded). This is not
4945 * a problem for initialization of the 'to be expanded' queue though, as no packed ID can be
4946 * directly linked currently, they are only brough in indirectly, i.e. during the expansion
4947 * process itself.
4948 *
4949 * So just looping on the 'main'/root Main of the read library is fine here currently. */
4950 ID *id_iter;
4951 FOREACH_MAIN_ID_BEGIN (mainvar, id_iter) {
4953 expander.ids_to_expand.push(id_iter);
4954 }
4955 }
4957
4958 while (!expander.ids_to_expand.empty()) {
4959 id_iter = expander.ids_to_expand.front();
4960 expander.ids_to_expand.pop();
4962
4963 /* Original (current) ID pointer can be considered as valid, but _not_ its own pointers to
4964 * other IDs - the already loaded ones will be valid, but the yet-to-be-read ones will not.
4965 * Expanding should _not_ require processing of UI ID pointers.
4966 * Expanding should never modify ID pointers themselves.
4967 * Handling of DNA deprecated data should never be needed in undo case. */
4969 ((!fd || (fd->flags & FD_FLAGS_IS_MEMFILE)) ?
4970 IDWALK_NOP :
4972 BKE_library_foreach_ID_link(nullptr, id_iter, expand_cb, &expander, flag);
4973
4975 }
4976}
4977
4979
4980/* -------------------------------------------------------------------- */
4983
4984/* returns true if the item was found
4985 * but it may already have already been appended/linked */
4987 Main *mainl, FileData *fd, const short idcode, const char *name, const int flag)
4988{
4989 BHead *bhead = find_bhead_from_code_name(fd, idcode, name);
4990 ID *id;
4991
4992 const bool use_placeholders = (flag & BLO_LIBLINK_USE_PLACEHOLDERS) != 0;
4993 const bool force_indirect = (flag & BLO_LIBLINK_FORCE_INDIRECT) != 0;
4994
4996
4997 if (bhead && blo_bhead_is_id_valid_type(bhead)) {
4998 id = library_id_is_yet_read(fd, mainl, bhead);
4999 if (id == nullptr) {
5000 /* not read yet */
5001 const int tag = ((force_indirect ? ID_TAG_INDIRECT : ID_TAG_EXTERN) | fd->id_tag_extra);
5002 ID_Readfile_Data::Tags id_read_tags{};
5003 id_read_tags.needs_expanding = true;
5004 read_libblock(fd, mainl, bhead, tag, id_read_tags, false, &id);
5005
5006 if (id) {
5007 /* sort by name in list */
5008 ListBase *lb = which_libbase(mainl, idcode);
5009 id_sort_by_name(lb, id, nullptr);
5010 }
5011 }
5012 else {
5013 /* already linked */
5014 CLOG_WARN(&LOG, "Append: ID '%s' is already linked", id->name);
5015 oldnewmap_lib_insert(fd, bhead->old, id, bhead->code);
5016 if (!force_indirect && (id->tag & ID_TAG_INDIRECT)) {
5017 id->tag &= ~ID_TAG_INDIRECT;
5018 id->flag &= ~ID_FLAG_INDIRECT_WEAK_LINK;
5019 id->tag |= ID_TAG_EXTERN;
5020 }
5021 }
5022 }
5023 else if (use_placeholders) {
5024 /* XXX flag part is weak! */
5025 id = create_placeholder(
5026 mainl, idcode, name, force_indirect ? ID_TAG_INDIRECT : ID_TAG_EXTERN, false);
5027 }
5028 else {
5029 id = nullptr;
5030 }
5031
5032 /* NOTE: `id` may be `nullptr` even if a BHead was found, in case e.g. it is an invalid BHead. */
5033
5034 return id;
5035}
5036
5038 BlendHandle **bh,
5039 const short idcode,
5040 const char *name,
5042{
5043 FileData *fd = (FileData *)(*bh);
5044
5045 ID *ret_id = nullptr;
5046 if (!mainl->is_read_invalid) {
5047 ret_id = link_named_part(mainl, fd, idcode, name, params->flag);
5048 }
5049
5050 if (mainl->is_read_invalid) {
5051 return nullptr;
5052 }
5053 return ret_id;
5054}
5055
5056/* common routine to append/link something from a library */
5057
5059 FileData *fd,
5060 const char *filepath,
5061 const int id_tag_extra)
5062{
5063 Main *mainl;
5064
5065 /* Only allow specific tags to be set as extra,
5066 * otherwise this could conflict with library loading logic.
5067 * Other flags can be added here, as long as they are safe. */
5068 BLI_assert((id_tag_extra & ~ID_TAG_TEMP_MAIN) == 0);
5069
5070 fd->id_tag_extra = id_tag_extra;
5071
5072 fd->bmain = mainvar;
5073
5074 /* Add already existing packed data-blocks to map so that they are not loaded again. */
5075 ID *id;
5076 FOREACH_MAIN_ID_BEGIN (mainvar, id) {
5077 if (ID_IS_PACKED(id)) {
5078 fd->id_by_deep_hash->add(id->deep_hash, id);
5079 }
5080 }
5082
5083 /* make mains */
5084 blo_split_main(mainvar);
5085
5086 /* Find or create a Main matching the current library filepath. */
5087 /* Note: Directly linking packed IDs is not supported currently. */
5089 fd, filepath, BKE_main_blendfile_path(mainvar), nullptr, nullptr, false);
5090 fd->fd_bmain = mainl;
5091 if (mainl->curlib) {
5092 mainl->curlib->runtime->filedata = fd;
5093 /* This filedata is owned and managed by the calling code. */
5094 mainl->curlib->runtime->is_filedata_owner = false;
5095 }
5096
5097 /* needed for do_version */
5098 mainl->versionfile = short(fd->fileversion);
5101
5102 return mainl;
5103}
5104
5106 Main *bmain,
5107 const int flag,
5108 const int id_tag_extra)
5109{
5110 memset(params, 0, sizeof(*params));
5111 params->bmain = bmain;
5112 params->flag = flag;
5113 params->id_tag_extra = id_tag_extra;
5114}
5115
5117 Main *bmain,
5118 const int flag,
5119 const int id_tag_extra,
5120 /* Context arguments. */
5121 Scene *scene,
5122 ViewLayer *view_layer,
5123 const View3D *v3d)
5124{
5125 BLO_library_link_params_init(params, bmain, flag, id_tag_extra);
5126 if (scene != nullptr) {
5127 params->context.scene = scene;
5128 params->context.view_layer = view_layer;
5129 params->context.v3d = v3d;
5130 }
5131}
5132
5134 const char *filepath,
5136{
5137 FileData *fd = reinterpret_cast<FileData *>(*bh);
5138 return library_link_begin(params->bmain, fd, filepath, params->id_tag_extra);
5139}
5140
5141static void split_main_newid(Main *mainptr, Main *main_newid)
5142{
5143 /* We only copy the necessary subset of data in this temp main. */
5144 main_newid->versionfile = mainptr->versionfile;
5145 main_newid->subversionfile = mainptr->subversionfile;
5146 STRNCPY(main_newid->filepath, mainptr->filepath);
5147 main_newid->curlib = mainptr->curlib;
5148 main_newid->colorspace = mainptr->colorspace;
5149
5150 MainListsArray lbarray = BKE_main_lists_get(*mainptr);
5151 MainListsArray lbarray_newid = BKE_main_lists_get(*main_newid);
5152 int i = lbarray.size();
5153 while (i--) {
5154 BLI_listbase_clear(lbarray_newid[i]);
5155
5156 LISTBASE_FOREACH_MUTABLE (ID *, id, lbarray[i]) {
5157 if (id->tag & ID_TAG_NEW) {
5158 BLI_remlink(lbarray[i], id);
5159 BLI_addtail(lbarray_newid[i], id);
5160 }
5161 }
5162 }
5163}
5164
5165static void library_link_end(Main *mainl, FileData **fd, const int flag, ReportList *reports)
5166{
5167 Main *mainvar = (*fd)->bmain;
5168 Library *curlib;
5169
5170 if (mainl->id_map == nullptr) {
5171 mainl->id_map = BKE_main_idmap_create(mainl, false, nullptr, MAIN_IDMAP_TYPE_NAME);
5172 }
5173
5174 /* make main consistent */
5175 expand_main(*fd, mainl, expand_doit_library);
5176
5178 *fd, reports, mainl->has_forward_compatibility_issues, mainl->curlib->runtime->filepath_abs);
5179
5180 /* Do this when expand found other libraries. */
5181 read_libraries(*fd);
5182
5183 curlib = mainl->curlib;
5184
5185 /* make the lib path relative if required */
5186 if (flag & FILE_RELPATH) {
5187 /* use the full path, this could have been read by other library even */
5188 STRNCPY(curlib->filepath, curlib->runtime->filepath_abs);
5189
5190 /* uses current .blend file as reference */
5192 }
5193
5194 blo_join_main(mainvar);
5195 mainl = nullptr; /* blo_join_main free's mainl, can't use anymore */
5196
5197 if (mainvar->is_read_invalid) {
5198 return;
5199 }
5200
5201 lib_link_all(*fd, mainvar);
5203 after_liblink_merged_bmain_process(mainvar, (*fd)->reports);
5204 }
5205
5206 /* Some versioning code does expect some proper userrefcounting, e.g. in conversion from
5207 * groups to collections... We could optimize out that first call when we are reading a
5208 * current version file, but again this is really not a bottle neck currently. So not worth
5209 * it. */
5210 BKE_main_id_refcount_recompute(mainvar, false);
5211
5212 /* FIXME: This is suspiciously early call compared to similar process in
5213 * #blo_read_file_internal, where it is called towards the very end, after all do_version,
5214 * liboverride updates etc. have been done. */
5215 /* FIXME: Probably also need to forbid layer collections updates until this call, as done in
5216 * #blo_read_file_internal? */
5218
5219 /* Yep, second splitting... but this is a very cheap operation, so no big deal. */
5220 blo_split_main(mainvar);
5221 Main *main_newid = BKE_main_new();
5222 for (Main *mainlib : mainvar->split_mains->as_span().drop_front(1)) {
5223
5224 BLI_assert(mainlib->versionfile != 0 || BKE_main_is_empty(mainlib));
5225 /* We need to split out IDs already existing,
5226 * or they will go again through do_versions - bad, very bad! */
5227 split_main_newid(mainlib, main_newid);
5228
5229 do_versions_after_linking((main_newid->curlib && main_newid->curlib->runtime->filedata) ?
5230 main_newid->curlib->runtime->filedata :
5231 *fd,
5232 main_newid);
5233 IMB_colormanagement_working_space_convert(main_newid, mainvar);
5234
5235 add_main_to_main(mainlib, main_newid);
5236
5237 if (mainlib->is_read_invalid) {
5238 break;
5239 }
5240 }
5241
5242 blo_join_main(mainvar);
5243
5244 if (mainvar->is_read_invalid) {
5245 BKE_main_free(main_newid);
5246 return;
5247 }
5248
5249 /* This does not take into account old, deprecated data, so we also have to do it after
5250 * `do_versions_after_linking()`. */
5251 BKE_main_id_refcount_recompute(mainvar, false);
5252
5253 /* After all data has been read and versioned, uses ID_TAG_NEW. */
5255
5257
5258 /* Apply overrides of newly linked data if needed. Already existing IDs need to split out, to
5259 * avoid re-applying their own overrides. */
5260 BLI_assert(BKE_main_is_empty(main_newid));
5261 split_main_newid(mainvar, main_newid);
5262 BKE_lib_override_library_main_validate(main_newid, (*fd)->reports->reports);
5264 add_main_to_main(mainvar, main_newid);
5265 BKE_main_free(main_newid);
5266
5267 BKE_main_id_tag_all(mainvar, ID_TAG_NEW, false);
5268
5269 /* FIXME Temporary 'fix' to a problem in how temp ID are copied in
5270 * `BKE_lib_override_library_main_update`, see #103062.
5271 * Proper fix involves first addressing #90610. */
5274 }
5275
5276 /* Make all relative paths, relative to the open blend file. */
5278
5279 /* patch to prevent switch_endian happens twice */
5280 /* FIXME This is extremely bad design, #library_link_end should probably _always_ free the file
5281 * data? */
5282 if ((*fd)->flags & FD_FLAGS_SWITCH_ENDIAN) {
5283 /* Big Endian blend-files are not supported for linking. */
5285 blo_filedata_free(*fd);
5286 *fd = nullptr;
5287 }
5288
5289 /* Sanity checks. */
5290 blo_read_file_checks(mainvar);
5291}
5292
5294 BlendHandle **bh,
5296 ReportList *reports)
5297{
5298 FileData *fd = reinterpret_cast<FileData *>(*bh);
5299
5300 if (!mainl->is_read_invalid) {
5301 library_link_end(mainl, &fd, params->flag, reports);
5302 }
5303
5304 LISTBASE_FOREACH (Library *, lib, &params->bmain->libraries) {
5305 /* Now we can clear this runtime library filedata, it is not needed anymore. */
5306 /* TODO: In the future, could be worth keeping them in case data are linked from several
5307 * libraries at once? To avoid closing and re-opening the same file several times. Would need
5308 * a global cleanup callback then once all linking is done, though. */
5310 }
5311
5312 *bh = reinterpret_cast<BlendHandle *>(fd);
5313}
5314
5315void *BLO_library_read_struct(FileData *fd, BHead *bh, const char *blockname)
5316{
5317 return read_struct(fd, bh, blockname, INDEX_ID_NULL);
5318}
5319
5321
5322/* -------------------------------------------------------------------- */
5325
5326static int has_linked_ids_to_read(Main *mainvar)
5327{
5328 MainListsArray lbarray = BKE_main_lists_get(*mainvar);
5329 int a = lbarray.size();
5330 while (a--) {
5331 LISTBASE_FOREACH (ID *, id, lbarray[a]) {
5333 !(id->flag & ID_FLAG_INDIRECT_WEAK_LINK))
5334 {
5335 return true;
5336 }
5337 }
5338 }
5339
5340 return false;
5341}
5342
5344 FileData *basefd, FileData *fd, Main *mainvar, ID *id, ID **r_id)
5345{
5346 BHead *bhead = nullptr;
5347 const bool is_valid = BKE_idtype_idcode_is_linkable(GS(id->name)) ||
5348 ((id->tag & ID_TAG_EXTERN) == 0);
5349
5350 if (fd) {
5351 /* About future longer ID names: This is one of the main places that prevent linking IDs with
5352 * names longer than MAX_ID_NAME - 1.
5353 *
5354 * See also #read_file_bhead_idname_map_create. */
5355 bhead = find_bhead_from_idname(fd, id->name);
5356 }
5357
5358 if (!is_valid) {
5359 BLO_reportf_wrap(basefd->reports,
5360 RPT_ERROR,
5361 RPT_("LIB: %s: '%s' is directly linked from '%s' (parent '%s'), but is a "
5362 "non-linkable data type"),
5364 id->name + 2,
5365 mainvar->curlib->runtime->filepath_abs,
5367 }
5368
5370 id->flag &= ~ID_FLAG_INDIRECT_WEAK_LINK;
5371
5372 if (bhead) {
5374 // printf("read lib block %s\n", id->name);
5375 read_libblock(fd, mainvar, bhead, id->tag, BLO_readfile_id_runtime_tags(*id), false, r_id);
5376 }
5377 else {
5378 CLOG_DEBUG(&LOG,
5379 "LIB: %s: '%s' missing from '%s', parent '%s'",
5381 id->name + 2,
5382 mainvar->curlib->runtime->filepath_abs,
5384 basefd->reports->count.missing_linked_id++;
5385
5386 /* Generate a placeholder for this ID (simplified version of read_libblock actually...). */
5387 if (r_id) {
5388 *r_id = is_valid ? create_placeholder(mainvar,
5389 GS(id->name),
5390 id->name + 2,
5391 id->tag,
5392 id->override_library != nullptr) :
5393 nullptr;
5394 }
5395 }
5396}
5397
5398static void read_library_linked_ids(FileData *basefd, FileData *fd, Main *mainvar)
5399{
5401
5402 MainListsArray lbarray = BKE_main_lists_get(*mainvar);
5403 int a = lbarray.size();
5404 while (a--) {
5405 ID *id = static_cast<ID *>(lbarray[a]->first);
5406
5407 while (id) {
5408 ID *id_next = static_cast<ID *>(id->next);
5411 {
5412 BLI_remlink(lbarray[a], id);
5413 if (mainvar->id_map != nullptr) {
5414 BKE_main_idmap_remove_id(mainvar->id_map, id);
5415 }
5416
5417 /* When playing with lib renaming and such, you may end with cases where
5418 * you have more than one linked ID of the same data-block from same
5419 * library. This is absolutely horrible, hence we use a ghash to ensure
5420 * we go back to a single linked data when loading the file. */
5421 ID *realid = loaded_ids.lookup_default(id->name, nullptr);
5422 if (!realid) {
5423 read_library_linked_id(basefd, fd, mainvar, id, &realid);
5424 loaded_ids.add_overwrite(id->name, realid);
5425 }
5426
5427 /* `realid` shall never be nullptr - unless some source file/lib is broken
5428 * (known case: some directly linked shape-key from a missing lib...). */
5429 // BLI_assert(*realid != nullptr);
5430
5431 /* Now that we have a real ID, replace all pointers to placeholders in
5432 * fd->libmap with pointers to the real data-blocks. We do this for all
5433 * libraries since multiple might be referencing this ID. */
5435
5436 /* Transfer the readfile data from the placeholder to the real ID, but
5437 * only if the real ID has no readfile data yet. The same realid may be
5438 * referred to by multiple placeholders. */
5439 if (realid && !realid->runtime->readfile_data) {
5440 realid->runtime->readfile_data = id->runtime->readfile_data;
5441 id->runtime->readfile_data = nullptr;
5442 }
5443
5444 /* Ensure that the runtime pointer, and its 'readfile' sub-data, are properly freed, as
5445 * this ID placeholder does not go through versioning (the usual place where this data is
5446 * freed). Since `id` is not a real ID, this shouldn't follow any pointers to embedded IDs.
5447 *
5448 * WARNING! This placeholder ID is only an ID struct, with a very small subset of regular
5449 * ID common data actually valid and needing to be freed. Therefore, calling
5450 * #BKE_libblock_free_data on it would not work. */
5452
5453 MEM_freeN(id);
5454 }
5455 id = id_next;
5456 }
5457
5458 loaded_ids.clear();
5459 }
5460
5462 basefd->reports->reports,
5464 mainvar->curlib->runtime->filepath_abs);
5465}
5466
5467static void read_library_clear_weak_links(FileData *basefd, Main *mainvar)
5468{
5469 /* Any remaining weak links at this point have been lost, silently drop
5470 * those by setting them to nullptr pointers. */
5471 MainListsArray lbarray = BKE_main_lists_get(*mainvar);
5472 int a = lbarray.size();
5473 while (a--) {
5474 ID *id = static_cast<ID *>(lbarray[a]->first);
5475
5476 while (id) {
5477 ID *id_next = static_cast<ID *>(id->next);
5478
5479 /* This function also visits already-loaded data-blocks, and thus their
5480 * `readfile_data` field might already have been freed. */
5483 {
5484 CLOG_DEBUG(&LOG, "Dropping weak link to '%s'", id->name);
5485 change_link_placeholder_to_real_ID_pointer(basefd, id, nullptr);
5486 BLI_freelinkN(lbarray[a], id);
5487 }
5488 id = id_next;
5489 }
5490 }
5491}
5492
5493static FileData *read_library_file_data(FileData *basefd, Main *bmain, Main *lib_bmain)
5494{
5495 FileData *fd = lib_bmain->curlib->runtime->filedata;
5496
5497 if (fd != nullptr) {
5498 /* File already open. */
5499 return fd;
5500 }
5501
5502 if (lib_bmain->curlib->packedfile) {
5503 /* Read packed file. */
5504 const PackedFile *pf = lib_bmain->curlib->packedfile;
5505
5506 BLO_reportf_wrap(basefd->reports,
5507 RPT_INFO,
5508 RPT_("Read packed library: '%s', parent '%s'"),
5509 lib_bmain->curlib->filepath,
5510 library_parent_filepath(lib_bmain->curlib));
5511 fd = blo_filedata_from_memory(pf->data, pf->size, basefd->reports);
5512
5513 /* Needed for library_append and read_libraries. */
5514 STRNCPY(fd->relabase, lib_bmain->curlib->runtime->filepath_abs);
5515 }
5516 else {
5517 /* Read file on disk. */
5518 BLO_reportf_wrap(basefd->reports,
5519 RPT_INFO,
5520 RPT_("Read library: '%s', '%s', parent '%s'"),
5521 lib_bmain->curlib->runtime->filepath_abs,
5522 lib_bmain->curlib->filepath,
5523 library_parent_filepath(lib_bmain->curlib));
5524 fd = blo_filedata_from_file(lib_bmain->curlib->runtime->filepath_abs, basefd->reports);
5525 }
5526
5527 if (fd) {
5528 /* `mainptr` is sharing the same `split_mains`, so all libraries are added immediately in a
5529 * single vectorset. It used to be that all FileData's had their own list, but with indirectly
5530 * linking this meant that not all duplicate libraries were catched properly. */
5531 fd->bmain = bmain;
5532 fd->fd_bmain = lib_bmain;
5533
5534 fd->reports = basefd->reports;
5535
5536 if (fd->libmap) {
5538 }
5539
5540 fd->libmap = oldnewmap_new();
5541 fd->id_by_deep_hash = basefd->id_by_deep_hash;
5542
5543 lib_bmain->curlib->runtime->filedata = fd;
5544 lib_bmain->curlib->runtime->is_filedata_owner = true;
5545 lib_bmain->versionfile = fd->fileversion;
5546
5547 /* subversion */
5548 read_file_version_and_colorspace(fd, lib_bmain);
5550 }
5551 else {
5552 lib_bmain->curlib->runtime->filedata = nullptr;
5553 lib_bmain->curlib->runtime->is_filedata_owner = false;
5554 lib_bmain->curlib->id.tag |= ID_TAG_MISSING;
5555 /* Set lib version to current main one... Makes assert later happy. */
5556 lib_bmain->versionfile = lib_bmain->curlib->runtime->versionfile = bmain->versionfile;
5557 lib_bmain->subversionfile = lib_bmain->curlib->runtime->subversionfile = bmain->subversionfile;
5558 lib_bmain->colorspace = lib_bmain->curlib->runtime->colorspace = bmain->colorspace;
5559 }
5560
5561 if (fd == nullptr) {
5562 BLO_reportf_wrap(basefd->reports,
5563 RPT_INFO,
5564 RPT_("Cannot find lib '%s'"),
5565 lib_bmain->curlib->runtime->filepath_abs);
5566 basefd->reports->count.missing_libraries++;
5567 }
5568
5569 return fd;
5570}
5571
5572static void read_libraries(FileData *basefd)
5573{
5574 Main *bmain = basefd->bmain;
5575 BLI_assert(bmain->split_mains);
5576 bool do_it = true;
5577
5578 /* At this point the base blend file has been read, and each library blend
5579 * encountered so far has a main with placeholders for linked data-blocks.
5580 *
5581 * Now we will read the library blend files and replace the placeholders
5582 * with actual data-blocks. We loop over library mains multiple times in
5583 * case a library needs to link additional data-blocks from another library
5584 * that had been read previously. */
5585 while (do_it) {
5586 do_it = false;
5587
5588 /* Loop over mains of all library blend files encountered so far. Note
5589 * this list gets longer as more indirectly library blends are found. */
5590 for (int i = 1; i < bmain->split_mains->size(); i++) {
5591 Main *libmain = (*bmain->split_mains)[i];
5592 BLI_assert(libmain->curlib);
5593 /* Always skip archived libraries here, these should _never_ need to be processed here, as
5594 * their data is local data from a blendfile perspective. */
5595 if (libmain->curlib->flag & LIBRARY_FLAG_IS_ARCHIVE) {
5597 continue;
5598 }
5599 /* Does this library have any more linked data-blocks we need to read? */
5600 if (has_linked_ids_to_read(libmain)) {
5601 CLOG_DEBUG(&LOG,
5602 "Reading linked data-blocks from %s (%s)",
5603 libmain->curlib->id.name,
5604 libmain->curlib->filepath);
5605
5606 /* Open file if it has not been done yet. */
5607 FileData *fd = read_library_file_data(basefd, bmain, libmain);
5608
5609 if (fd) {
5610 do_it = true;
5611
5612 if (libmain->id_map == nullptr) {
5613 libmain->id_map = BKE_main_idmap_create(libmain, false, nullptr, MAIN_IDMAP_TYPE_NAME);
5614 }
5615 }
5616
5617 /* Read linked data-blocks for each link placeholder, and replace
5618 * the placeholder with the real data-block. */
5619 read_library_linked_ids(basefd, fd, libmain);
5620
5621 /* Test if linked data-blocks need to read further linked data-blocks
5622 * and create link placeholders for them. */
5623 expand_main(fd, libmain, expand_doit_library);
5624 }
5625 }
5626 }
5627
5628 for (Main *libmain : bmain->split_mains->as_span().drop_front(1)) {
5629 /* Drop weak links for which no data-block was found.
5630 * Since this can remap pointers in `libmap` of all libraries, it needs to be performed in its
5631 * own loop, before any call to `lib_link_all` (and the freeing of the libraries' filedata). */
5632 read_library_clear_weak_links(basefd, libmain);
5633 }
5634
5635 Main *main_newid = BKE_main_new();
5636 for (Main *libmain : bmain->split_mains->as_span().drop_front(1)) {
5637 /* Do versioning for newly added linked data-blocks. If no data-blocks
5638 * were read from a library versionfile will still be zero and we can
5639 * skip it. */
5640 if (libmain->versionfile) {
5641 /* Split out already existing IDs to avoid them going through
5642 * do_versions multiple times, which would have bad consequences. */
5643 split_main_newid(libmain, main_newid);
5644
5645 /* `filedata` can be NULL when loading linked data from nonexistent or invalid library
5646 * reference. Or during linking/appending, when processing data from a library not involved
5647 * in the current linking/appending operation.
5648 *
5649 * Skip versioning in these cases, since the only IDs here will be placeholders (missing
5650 * lib), or already existing IDs (linking/appending). */
5651 if (libmain->curlib->runtime->filedata) {
5652 do_versions(libmain->curlib->runtime->filedata, libmain->curlib, main_newid);
5653 }
5654
5655 add_main_to_main(libmain, main_newid);
5656 }
5657
5658 /* Lib linking. */
5659 if (libmain->curlib->runtime->filedata) {
5660 lib_link_all(libmain->curlib->runtime->filedata, libmain);
5661 }
5662
5663 /* NOTE: No need to call #do_versions_after_linking() or #BKE_main_id_refcount_recompute()
5664 * here, as this function is only called for library 'subset' data handling, as part of
5665 * either full blend-file reading (#blo_read_file_internal()), or library-data linking
5666 * (#library_link_end()).
5667 *
5668 * For this to work reliably, `mainptr->curlib->runtime->filedata` also needs to be freed after
5669 * said versioning code has run. */
5670 }
5671 BKE_main_free(main_newid);
5672}
5673
5675 void *new_address,
5676 const void * /*old_address*/,
5677 const size_t expected_size)
5678{
5679 if (new_address != nullptr) {
5680 /* Not testing equality, since size might have been aligned up,
5681 * or might be passed the size of a base struct with inheritance. */
5682 if (MEM_allocN_len(new_address) < expected_size) {
5684 (*fd->bmain->split_mains)[fd->bmain->split_mains->size() - 1],
5685 "Corrupt .blend file, unexpected data size.");
5686 /* Return null to trigger a hard-crash rather than allowing readfile code to further access
5687 * this invalid block of memory.
5688 *
5689 * It could also potentially allow the calling code to do its own error checking and abort
5690 * reading process, but that is not implemented currently. */
5691 return nullptr;
5692 }
5693 }
5694
5695 return new_address;
5696}
5697
5698void *BLO_read_get_new_data_address(BlendDataReader *reader, const void *old_address)
5699{
5700 return newdataadr(reader->fd, old_address);
5701}
5702
5704 const void *old_address,
5705 const size_t expected_size)
5706{
5707 void *new_address = newdataadr_no_us(reader->fd, old_address);
5708 return blo_verify_data_address(reader->fd, new_address, old_address, expected_size);
5709}
5710
5712 const void *old_address,
5713 const size_t expected_size)
5714{
5715 void *new_address = newdataadr(reader->fd, old_address);
5716 return blo_verify_data_address(reader->fd, new_address, old_address, expected_size);
5717}
5718
5720 const char *struct_name,
5721 const int64_t items_num,
5722 const void *old_address)
5723{
5724 const int struct_index = DNA_struct_find_with_alias(reader->fd->memsdna, struct_name);
5725 BLI_assert(STREQ(DNA_struct_identifier(const_cast<SDNA *>(reader->fd->memsdna), struct_index),
5726 struct_name));
5727 const size_t struct_size = size_t(DNA_struct_size(reader->fd->memsdna, struct_index));
5728 return BLO_read_struct_array_with_size(reader, old_address, struct_size * items_num);
5729}
5730
5732 ID *self_id,
5733 const bool is_linked_only,
5734 ID *id)
5735{
5736 return static_cast<ID *>(newlibadr(reader->fd, self_id, is_linked_only, id));
5737}
5738
5740{
5741 return BKE_main_idmap_lookup_uid(reader->fd->new_idmap_uid, session_uid);
5742}
5743
5745{
5746 return reader->fd->fileversion;
5747}
5748
5750 const size_t expected_elem_size,
5751 ListBase *list)
5752{
5753 if (BLI_listbase_is_empty(list)) {
5754 return;
5755 }
5756
5757 list->first = BLO_read_struct_array_with_size(reader, list->first, expected_elem_size);
5758 Link *ln = static_cast<Link *>(list->first);
5759 Link *prev = nullptr;
5760 while (ln) {
5761 ln->next = static_cast<Link *>(
5762 BLO_read_struct_array_with_size(reader, ln->next, expected_elem_size));
5763 ln->prev = prev;
5764 prev = ln;
5765 ln = ln->next;
5766 }
5767 list->last = prev;
5768}
5769
5770void BLO_read_char_array(BlendDataReader *reader, const int64_t array_size, char **ptr_p)
5771{
5772 *ptr_p = reinterpret_cast<char *>(
5773 BLO_read_struct_array_with_size(reader, *((void **)ptr_p), sizeof(char) * array_size));
5774}
5775
5776void BLO_read_uint8_array(BlendDataReader *reader, const int64_t array_size, uint8_t **ptr_p)
5777{
5778 *ptr_p = reinterpret_cast<uint8_t *>(
5779 BLO_read_struct_array_with_size(reader, *((void **)ptr_p), sizeof(uint8_t) * array_size));
5780}
5781
5782void BLO_read_int8_array(BlendDataReader *reader, const int64_t array_size, int8_t **ptr_p)
5783{
5784 *ptr_p = reinterpret_cast<int8_t *>(
5785 BLO_read_struct_array_with_size(reader, *((void **)ptr_p), sizeof(int8_t) * array_size));
5786}
5787
5788void BLO_read_int16_array(BlendDataReader *reader, const int64_t array_size, int16_t **ptr_p)
5789{
5790 *ptr_p = reinterpret_cast<int16_t *>(
5791 BLO_read_struct_array_with_size(reader, *((void **)ptr_p), sizeof(int16_t) * array_size));
5792 BLI_assert((reader->fd->flags & FD_FLAGS_SWITCH_ENDIAN) == 0);
5793}
5794
5795void BLO_read_int32_array(BlendDataReader *reader, const int64_t array_size, int32_t **ptr_p)
5796{
5797 *ptr_p = reinterpret_cast<int32_t *>(
5798 BLO_read_struct_array_with_size(reader, *((void **)ptr_p), sizeof(int32_t) * array_size));
5799 BLI_assert((reader->fd->flags & FD_FLAGS_SWITCH_ENDIAN) == 0);
5800}
5801
5802void BLO_read_uint32_array(BlendDataReader *reader, const int64_t array_size, uint32_t **ptr_p)
5803{
5804 *ptr_p = reinterpret_cast<uint32_t *>(
5805 BLO_read_struct_array_with_size(reader, *((void **)ptr_p), sizeof(uint32_t) * array_size));
5806 BLI_assert((reader->fd->flags & FD_FLAGS_SWITCH_ENDIAN) == 0);
5807}
5808
5809void BLO_read_float_array(BlendDataReader *reader, const int64_t array_size, float **ptr_p)
5810{
5811 *ptr_p = reinterpret_cast<float *>(
5812 BLO_read_struct_array_with_size(reader, *((void **)ptr_p), sizeof(float) * array_size));
5813 BLI_assert((reader->fd->flags & FD_FLAGS_SWITCH_ENDIAN) == 0);
5814}
5815
5816void BLO_read_float3_array(BlendDataReader *reader, const int64_t array_size, float **ptr_p)
5817{
5818 BLO_read_float_array(reader, array_size * 3, ptr_p);
5819}
5820
5821void BLO_read_double_array(BlendDataReader *reader, const int64_t array_size, double **ptr_p)
5822{
5823 *ptr_p = reinterpret_cast<double *>(
5824 BLO_read_struct_array_with_size(reader, *((void **)ptr_p), sizeof(double) * array_size));
5825 BLI_assert((reader->fd->flags & FD_FLAGS_SWITCH_ENDIAN) == 0);
5826}
5827
5828void BLO_read_string(BlendDataReader *reader, char **ptr_p)
5829{
5830 BLO_read_data_address(reader, ptr_p);
5831
5832#ifndef NDEBUG
5833 const char *str = *ptr_p;
5834 if (str) {
5835 /* Verify that we have a null terminator. */
5836 for (size_t len = MEM_allocN_len(str); len > 0; len--) {
5837 if (str[len - 1] == '\0') {
5838 return;
5839 }
5840 }
5841
5842 BLI_assert_msg(0, "Corrupt .blend file, expected string to be null terminated.");
5843 }
5844#endif
5845}
5846
5847void BLO_read_string(BlendDataReader *reader, char *const *ptr_p)
5848{
5849 BLO_read_string(reader, const_cast<char **>(ptr_p));
5850}
5851
5852void BLO_read_string(BlendDataReader *reader, const char **ptr_p)
5853{
5854 BLO_read_string(reader, const_cast<char **>(ptr_p));
5855}
5856
5858 const int64_t array_size,
5859 const uint64_t *src,
5860 uint32_t *dst)
5861{
5862 BLI_assert((reader->fd->flags & FD_FLAGS_SWITCH_ENDIAN) == 0);
5863 UNUSED_VARS_NDEBUG(reader);
5864 for (int i = 0; i < array_size; i++) {
5865 dst[i] = uint32_from_uint64_ptr(src[i]);
5866 }
5867}
5868
5870 const int64_t array_size,
5871 const uint32_t *src,
5872 uint64_t *dst)
5873{
5874 /* Match pointer conversion rules from bh8_from_bh4 and cast_pointer_32_to_64. */
5875 for (int i = 0; i < array_size; i++) {
5876 dst[i] = src[i];
5877 }
5878}
5879
5880void BLO_read_pointer_array(BlendDataReader *reader, const int64_t array_size, void **ptr_p)
5881{
5882 FileData *fd = reader->fd;
5883
5884 void *orig_array = newdataadr(fd, *ptr_p);
5885 if (orig_array == nullptr) {
5886 *ptr_p = nullptr;
5887 return;
5888 }
5889
5890 int file_pointer_size = fd->filesdna->pointer_size;
5891 int current_pointer_size = fd->memsdna->pointer_size;
5892
5893 void *final_array = nullptr;
5894
5895 if (file_pointer_size == current_pointer_size) {
5896 /* No pointer conversion necessary. */
5897 final_array = orig_array;
5898 }
5899 else if (file_pointer_size == 8 && current_pointer_size == 4) {
5900 /* Convert pointers from 64 to 32 bit. */
5901 final_array = MEM_malloc_arrayN(array_size, 4, "new pointer array");
5903 reader, array_size, (uint64_t *)orig_array, (uint32_t *)final_array);
5904 MEM_freeN(orig_array);
5905 }
5906 else if (file_pointer_size == 4 && current_pointer_size == 8) {
5907 /* Convert pointers from 32 to 64 bit. */
5908 final_array = MEM_malloc_arrayN(array_size, 8, "new pointer array");
5910 reader, array_size, (uint32_t *)orig_array, (uint64_t *)final_array);
5911 MEM_freeN(orig_array);
5912 }
5913 else {
5915 }
5916
5917 *ptr_p = final_array;
5918}
5919
5921 BlendDataReader *reader,
5922 const void **ptr_p,
5923 const blender::FunctionRef<const blender::ImplicitSharingInfo *()> read_fn)
5924{
5925 const uint64_t old_address_id = uint64_t(*ptr_p);
5926 if (BLO_read_data_is_undo(reader)) {
5927 if (reader->fd->flags & FD_FLAGS_IS_MEMFILE) {
5928 UndoReader *undo_reader = reinterpret_cast<UndoReader *>(reader->fd->file);
5929 const MemFile &memfile = *undo_reader->memfile;
5930 if (memfile.shared_storage) {
5931 /* Check if the data was saved with sharing-info. */
5932 if (const blender::ImplicitSharingInfoAndData *sharing_info_data =
5933 memfile.shared_storage->sharing_info_by_address_id.lookup_ptr(old_address_id))
5934 {
5935 /* Add a new owner of the data that is passed to the caller. */
5936 sharing_info_data->sharing_info->add_user();
5937 return *sharing_info_data;
5938 }
5939 }
5940 }
5941 }
5942
5943 if (const blender::ImplicitSharingInfoAndData *shared_data =
5944 reader->shared_data_by_stored_address.lookup_ptr(old_address_id))
5945 {
5946 /* The data was loaded before. No need to load it again. Just increase the user count to
5947 * indicate that it is shared. */
5948 if (shared_data->sharing_info) {
5949 shared_data->sharing_info->add_user();
5950 }
5951 return *shared_data;
5952 }
5953
5954 /* This is the first time this data is loaded. The callback also creates the corresponding
5955 * sharing info which may be reused later. */
5956 const blender::ImplicitSharingInfo *sharing_info = read_fn();
5957 const void *new_address = *ptr_p;
5958 const blender::ImplicitSharingInfoAndData shared_data{sharing_info, new_address};
5959 reader->shared_data_by_stored_address.add(old_address_id, shared_data);
5960 return shared_data;
5961}
5962
5964{
5965 return (reader->fd->flags & FD_FLAGS_IS_MEMFILE);
5966}
5967
5968void BLO_read_data_globmap_add(BlendDataReader *reader, void *oldaddr, void *newaddr)
5969{
5970 oldnewmap_insert(reader->fd->globmap, oldaddr, newaddr, 0);
5971}
5972
5974{
5975 link_glob_list(reader->fd, list);
5976}
5977
5979{
5980 return reader->fd->reports;
5981}
5982
5984{
5985 return (reader->fd->flags & FD_FLAGS_IS_MEMFILE);
5986}
5987
5989{
5990 return reader->main;
5991}
5992
5994{
5995 return reader->fd->reports;
5996}
5997
AnimData * BKE_animdata_from_id(const ID *id)
Definition anim_data.cc:83
void BKE_animdata_blend_read_data(BlendDataReader *reader, ID *id)
void BKE_asset_metadata_read(BlendDataReader *reader, AssetMetaData *asset_data)
Definition asset.cc:215
void BKE_asset_catalog_path_list_blend_read_data(BlendDataReader *reader, ListBase &catalog_path_list)
#define BLENDER_FILE_SUBVERSION
void BKE_blender_version_blendfile_string_from_values(char *str_buff, const size_t str_buff_maxncpy, const short file_version, const short file_subversion)
Definition blender.cc:156
#define BLENDER_FILE_VERSION
void BKE_collections_after_lib_link(Main *bmain)
void BKE_collection_blend_read_data(BlendDataReader *reader, Collection *collection, ID *owner_id)
void BKE_main_collections_parent_relations_rebuild(Main *bmain)
@ G_DEBUG
@ G_FILE_ASSET_EDIT_FILE
@ G_FILE_RECOVER_READ
#define IDP_BlendDataRead(reader, prop)
const IDTypeInfo * BKE_idtype_get_info_from_idtype_index(const int idtype_index)
Definition idtype.cc:127
const IDTypeInfo * BKE_idtype_get_info_from_id(const ID *id)
Definition idtype.cc:146
bool BKE_idtype_cache_key_cmp(const void *key_a_v, const void *key_b_v)
Definition idtype.cc:36
@ IDTYPE_FLAGS_NO_MEMFILE_UNDO
Definition BKE_idtype.hh:58
const char * BKE_idtype_idcode_to_name(short idcode)
Definition idtype.cc:164
bool BKE_idtype_idcode_is_linkable(short idcode)
Definition idtype.cc:197
void BKE_idtype_id_foreach_cache(ID *id, IDTypeForeachCacheFunctionCallback function_callback, void *user_data)
Definition idtype.cc:379
int BKE_idtype_idcode_to_index(short idcode)
Definition idtype.cc:228
uint BKE_idtype_cache_key_hash(const void *key_v)
Definition idtype.cc:28
bool BKE_idtype_idcode_is_valid(short idcode)
Definition idtype.cc:192
@ IDTYPE_CACHE_CB_FLAGS_PERSISTENT
void BKE_layer_collection_resync_forbid()
void BKE_layer_collection_resync_allow()
ViewLayer * BKE_view_layer_find(const Scene *scene, const char *layer_name)
void BKE_id_delete(Main *bmain, void *idv) ATTR_NONNULL()
IDNewNameResult BKE_id_new_name_validate(Main &bmain, ListBase &lb, ID &id, const char *newname, IDNewNameMode mode, bool do_linked_data)
Definition lib_id.cc:1903
void BKE_libblock_free_runtime_data(ID *id)
void BKE_id_free(Main *bmain, void *idv)
void id_sort_by_name(ListBase *lb, ID *id, ID *id_sorting_hint)
Definition lib_id.cc:1790
#define MAIN_ID_SESSION_UID_UNSET
void BKE_libblock_init_empty(ID *id) ATTR_NONNULL(1)
Definition lib_id.cc:1452
void BKE_lib_libblock_session_uid_ensure(ID *id)
Definition lib_id.cc:1477
void id_us_ensure_real(ID *id)
Definition lib_id.cc:313
void BKE_lib_id_swap_full(Main *bmain, ID *id_a, ID *id_b, const bool do_self_remap, const int self_remap_flags)
Definition lib_id.cc:1062
void * BKE_id_new(Main *bmain, short type, const char *name)
Definition lib_id.cc:1514
const char * BKE_id_name(const ID &id)
void BKE_libblock_runtime_ensure(ID &id)
Definition lib_id.cc:1316
void BKE_main_id_refcount_recompute(Main *bmain, bool do_linked_only)
Definition lib_id.cc:2035
ID * BKE_libblock_alloc_notest(short type) ATTR_WARN_UNUSED_RESULT
Definition lib_id.cc:1340
void BKE_main_id_tag_all(Main *mainvar, int tag, bool value)
Definition lib_id.cc:1224
void BKE_lib_override_library_main_validate(Main *bmain, ReportList *reports)
void BKE_lib_override_library_main_update(Main *bmain)
@ IDWALK_RET_NOP
@ IDWALK_CB_LOOPBACK
@ IDWALK_CB_EMBEDDED_NOT_OWNING
@ IDWALK_CB_EMBEDDED
@ IDWALK_CB_DIRECT_WEAK_LINK
@ IDWALK_CB_READFILE_IGNORE
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_DO_DEPRECATED_POINTERS
@ IDWALK_INCLUDE_UI
@ IDWALK_NOP
@ IDWALK_READONLY
@ IDWALK_NO_ORIG_POINTERS_ACCESS
@ ID_REMAP_SKIP_USER_CLEAR
@ ID_REMAP_SKIP_USER_REFCOUNT
@ ID_REMAP_SKIP_NEVER_NULL_USAGE
@ ID_REMAP_SKIP_UPDATE_TAGGING
@ ID_REMAP_NO_ORIG_POINTERS_ACCESS
@ LIBRARY_IS_ASSET_EDIT_FILE
@ LIBRARY_ASSET_EDITABLE
@ LIBRARY_TAG_RESYNC_REQUIRED
#define FOREACH_MAIN_ID_END
Definition BKE_main.hh:583
MainListsArray BKE_main_lists_get(Main &bmain)
Definition main.cc:987
ListBase * which_libbase(Main *bmain, short type)
Definition main.cc:902
#define MAIN_VERSION_FILE_ATLEAST(main, ver, subver)
Definition BKE_main.hh:658
#define FOREACH_MAIN_LISTBASE_ID_END
Definition BKE_main.hh:552
std::array< ListBase *, INDEX_ID_MAX - 1 > MainListsArray
Definition BKE_main.hh:645
#define FOREACH_MAIN_LISTBASE_ID_BEGIN(_lb, _id)
Definition BKE_main.hh:546
#define FOREACH_MAIN_LISTBASE_END
Definition BKE_main.hh:564
Main * BKE_main_new()
Definition main.cc:89
#define FOREACH_MAIN_LISTBASE_BEGIN(_bmain, _lb)
Definition BKE_main.hh:557
void BKE_main_free(Main *bmain)
Definition main.cc:192
#define FOREACH_MAIN_ID_BEGIN(_bmain, _id)
Definition BKE_main.hh:577
#define MAIN_VERSION_FILE_OLDER_OR_EQUAL(main, ver, subver)
Definition BKE_main.hh:666
#define BLEN_THUMB_MEMSIZE(_x, _y)
Definition BKE_main.hh:686
const char * BKE_main_blendfile_path(const Main *bmain) ATTR_NONNULL()
Definition main.cc:887
#define BLEN_THUMB_MEMSIZE_IS_VALID(_x, _y)
Definition BKE_main.hh:689
bool BKE_main_is_empty(Main *bmain)
Definition main.cc:462
const char * BKE_main_blendfile_path_from_global()
Definition main.cc:892
ID ID ID * BKE_main_idmap_lookup_uid(IDNameLib_Map *id_map, uint session_uid) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Main * BKE_main_idmap_main_get(IDNameLib_Map *id_map) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
IDNameLib_Map * BKE_main_idmap_create(Main *bmain, bool create_valid_ids_set, Main *old_bmain, int idmap_types) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition main_idmap.cc:77
void BKE_main_idmap_remove_id(IDNameLib_Map *id_map, const ID *id) ATTR_NONNULL()
void BKE_main_idmap_destroy(IDNameLib_Map *id_map) ATTR_NONNULL()
void BKE_main_idmap_insert_id(IDNameLib_Map *id_map, ID *id) ATTR_NONNULL()
ID * BKE_main_idmap_lookup_name(IDNameLib_Map *id_map, short id_type, const char *name, const Library *lib) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
@ MAIN_IDMAP_TYPE_UID
@ MAIN_IDMAP_TYPE_NAME
void BKE_main_ensure_invariants(Main &bmain, std::optional< blender::Span< ID * > > modified_ids=std::nullopt)
bool BKE_main_namemap_validate_and_fix(Main &bmain)
void BKE_main_namemap_clear(Main &bmain)
General operations, lookup, etc. for materials.
void BKE_object_materials_sync_length(Main *bmain, Object *ob, ID *id)
General operations, lookup, etc. for blender objects.
void BKE_packedfile_blend_read(BlendDataReader *reader, PackedFile **pf_p, blender::StringRefNull filepath)
void BKE_preferences_extension_repo_read_data(struct BlendDataReader *reader, bUserExtensionRepo *repo)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
eReportType
Definition BKE_report.hh:33
@ RPT_INFO
Definition BKE_report.hh:35
@ RPT_ERROR
Definition BKE_report.hh:39
@ RPT_WARNING
Definition BKE_report.hh:38
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:153
void BKE_report_log(eReportType type, const char *message, CLG_LogRef *log)
Definition report.cc:33
bool BKE_screen_blend_read_data(BlendDataReader *reader, bScreen *screen)
Definition screen.cc:141
@ STEP_UNDO
@ STEP_REDO
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_STATIC_ASSERT(a, msg)
Definition BLI_assert.h:83
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
#define ATTR_FALLTHROUGH
#define L_ENDIAN
#define ENDIAN_ORDER
File and directory operations.
#define O_BINARY
bool BLI_file_magic_is_gzip(const char header[4])
Definition fileops_c.cc:257
int BLI_stat(const char *path, BLI_stat_t *buffer) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
bool BLI_file_magic_is_zstd(const char header[4])
Definition fileops_c.cc:264
struct stat BLI_stat_t
int BLI_open(const char *filepath, int oflag, int pmode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
FileReader * BLI_filereader_new_mmap(int filedes) ATTR_WARN_UNUSED_RESULT
FileReader * BLI_filereader_new_zstd(FileReader *base) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
FileReader * BLI_filereader_new_file(int filedes) ATTR_WARN_UNUSED_RESULT
FileReader * BLI_filereader_new_gzip(FileReader *base) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
FileReader * BLI_filereader_new_memory(const void *data, size_t len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
bool BLI_ghash_haskey(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:819
GHash * BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:686
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:731
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition BLI_ghash.cc:707
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.cc:860
void void void BLI_movelisttolist(ListBase *dst, ListBase *src) ATTR_NONNULL(1
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(ListBase *lb)
void * BLI_findstring(const ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:608
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
void BLI_freelinkN(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:270
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:497
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:131
bool BLI_remlink_safe(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:154
int BLI_listbase_count(const ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:524
#define BLI_MEMARENA_STD_BUFSIZE
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)
void * BLI_memarena_alloc(MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
ATTR_WARN_UNUSED_RESULT const size_t num
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1
void void void const char * BLI_path_basename(const char *path) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
#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 BLI_path_cmp
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
size_t size_t size_t bool BLI_str_utf8_truncate_at_size(char *str, const size_t str_size)
size_t void BLI_uniquename_cb(blender::FunctionRef< bool(blender::StringRefNull)> unique_check, const char *defname, char delim, char *name, size_t name_maxncpy) ATTR_NONNULL(2
unsigned int uint
Platform independent time functions.
double BLI_time_now_seconds(void)
Definition time.cc:113
#define UNUSED_VARS(...)
#define UNUSED_VARS_NDEBUG(...)
#define SET_FLAG_FROM_TEST(value, test, flag)
#define UNLIKELY(x)
#define ELEM(...)
#define POINTER_OFFSET(v, ofs)
#define STREQ(a, b)
#define LIKELY(x)
Compatibility-like things for windows.
Utilities ensuring .blend file (i.e. Main) is in valid state during write and/or read process.
void BLO_main_validate_embedded_flag(Main *bmain, ReportList *reports)
bool BLO_main_validate_shapekeys(Main *bmain, ReportList *reports)
void BLO_main_validate_embedded_liboverrides(Main *bmain, ReportList *reports)
uint32_t uint32_from_uint64_ptr(uint64_t ptr)
@ BLO_CODE_ENDB
@ BLO_CODE_REND
@ BLO_CODE_TEST
@ BLO_CODE_GLOB
@ BLO_CODE_DATA
@ BLO_CODE_DNA1
@ BLO_CODE_USER
std::optional< BHead > BLO_readfile_read_bhead(FileReader *file, BHeadType type)
BlenderHeaderVariant BLO_readfile_blender_header_decode(FileReader *file)
#define MIN_SIZEOFBLENDERHEADER
std::variant< BlenderHeaderInvalid, BlenderHeaderUnknown, BlenderHeader > BlenderHeaderVariant
#define BLO_read_data_address(reader, ptr_p)
#define BLO_read_struct_list(reader, struct_name, list)
#define BLO_read_struct(reader, struct_name, ptr_p)
external readfile function prototypes.
@ BLO_LIBLINK_USE_PLACEHOLDERS
@ BLO_LIBLINK_COLLECTION_NO_HIERARCHY_REBUILD
@ BLO_LIBLINK_FORCE_INDIRECT
@ BLO_READ_SKIP_DATA
@ BLO_READ_SKIP_USERDEF
@ BLO_READ_SKIP_UNDO_OLD_MAIN
ID_Readfile_Data::Tags BLO_readfile_id_runtime_tags(ID &id)
Definition readfile.cc:2206
#define BLEN_THUMB_MEMSIZE_FILE(_x, _y)
@ BLENFILETYPE_BLEND
FileReader * BLO_memfile_new_filereader(MemFile *memfile, int undo_direction)
Definition undofile.cc:265
#define RPT_(msgid)
#define CLOG_ERROR(clg_ref,...)
Definition CLG_log.h:188
#define CLOG_DEBUG(clg_ref,...)
Definition CLG_log.h:191
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:189
#define CLOG_INFO(clg_ref,...)
Definition CLG_log.h:190
#define ID_IS_PACKED(_id)
Definition DNA_ID.h:700
@ ID_TAG_UNDO_OLD_ID_REUSED_UNCHANGED
Definition DNA_ID.h:936
@ ID_TAG_NEW
Definition DNA_ID.h:919
@ ID_TAG_UNDO_OLD_ID_REUSED_NOUNDO
Definition DNA_ID.h:947
@ ID_TAG_TEMP_MAIN
Definition DNA_ID.h:971
@ ID_TAG_INDIRECT
Definition DNA_ID.h:848
@ ID_TAG_EXTERN
Definition DNA_ID.h:842
@ ID_TAG_MISSING
Definition DNA_ID.h:867
@ ID_TAG_UNDO_OLD_ID_REREAD_IN_PLACE
Definition DNA_ID.h:954
@ ID_TAG_LIBOVERRIDE_NEED_RESYNC
Definition DNA_ID.h:906
#define ID_FAKE_USERS(id)
Definition DNA_ID.h:655
@ ID_RECALC_SOURCE
Definition DNA_ID.h:1143
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1118
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1074
@ ID_RECALC_ALL
Definition DNA_ID.h:1188
#define ID_IS_LINKED(_id)
Definition DNA_ID.h:694
#define MAX_ID_NAME
Definition DNA_ID.h:373
#define INDEX_ID_MAX
Definition DNA_ID.h:1360
@ INDEX_ID_NULL
Definition DNA_ID.h:1357
#define ID_TAG_KEEP_ON_UNDO
Definition DNA_ID.h:1046
@ ID_FLAG_INDIRECT_WEAK_LINK
Definition DNA_ID.h:780
@ ID_FLAG_LINKED_AND_PACKED
Definition DNA_ID.h:804
@ ID_FLAG_FAKEUSER
Definition DNA_ID.h:769
@ LIBRARY_FLAG_IS_ARCHIVE
Definition DNA_ID.h:593
@ ID_WM
@ ID_LI
@ ID_SCE
@ ID_AC
@ ID_SCR
@ ID_OB
#define ID_SCRN
#define ID_LINK_PLACEHOLDER
Object groups, one object can be in many groups at once.
@ CONSTRAINT_TYPE_ACTION
blenloader genfile private function prototypes
const char * DNA_struct_get_compareflags(const struct SDNA *oldsdna, const struct SDNA *newsdna)
void DNA_sdna_free(struct SDNA *sdna)
const struct SDNA * DNA_sdna_current_get(void)
int DNA_struct_find_with_alias(const struct SDNA *sdna, const char *str)
int DNA_struct_member_offset_by_name_with_alias(const struct SDNA *sdna, const char *stype, const char *vartype, const char *name)
int DNA_struct_size(const struct SDNA *sdna, int struct_index)
const char * DNA_struct_identifier(struct SDNA *sdna, int struct_index)
void * DNA_struct_reconstruct(const struct DNA_ReconstructInfo *reconstruct_info, int old_struct_index, int blocks, const void *old_blocks, const char *alloc_name)
struct SDNA * DNA_sdna_from_data(const void *data, int data_len, bool data_alloc, bool do_alias, const char **r_error_message)
struct DNA_ReconstructInfo * DNA_reconstruct_info_create(const struct SDNA *oldsdna, const struct SDNA *newsdna, const char *compare_flags)
void DNA_reconstruct_info_free(struct DNA_ReconstructInfo *reconstruct_info)
int DNA_struct_alignment(const struct SDNA *sdna, int struct_index)
@ SDNA_CMP_REMOVED
Definition DNA_genfile.h:64
@ SDNA_CMP_NOT_EQUAL
Definition DNA_genfile.h:69
void DNA_sdna_alias_data_ensure_structs_map(struct SDNA *sdna)
@ OB_MODE_EDIT
@ SCE_READFILE_LIBLINK_NEED_SETSCENE_CHECK
#define SDNA_RAW_DATA_STRUCT_INDEX
@ FILE_RELPATH
@ USER_MENU_TYPE_OPERATOR
void IMB_colormanagement_working_space_convert(Main *bmain, const blender::float3x3 &current_scene_linear_to_xyz, const blender::float3x3 &new_xyz_to_scene_linear, const bool depsgraph_tag=false, const bool linked_only=false, const bool editable_assets_only=false)
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v2
long long int int64_t
unsigned long long int uint64_t
void clear()
Definition BLI_map.hh:1038
const Value * lookup_ptr(const Key &key) const
Definition BLI_map.hh:508
bool add_overwrite(const Key &key, const Value &value)
Definition BLI_map.hh:325
ValueIterator values() const &
Definition BLI_map.hh:884
bool add(const Key &key, const Value &value)
Definition BLI_map.hh:295
void clear()
Definition BLI_map.hh:1038
bool add_overwrite(const Key &key, const Value &value)
Definition BLI_map.hh:325
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
void add_new(const Key &key)
Definition BLI_set.hh:233
int64_t size() const
void append(const T &value)
Span< T > as_span() const
const char * insert(const keyT &key, std::string alloc_string)
#define offsetof(t, d)
#define str(s)
#define GS(x)
#define pf(_x, _i)
Prefetch 64.
Definition gim_memory.h:48
#define main()
#define printf(...)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
format
#define LOG(level)
Definition log.h:97
void * MEM_mallocN(size_t len, const char *str)
Definition mallocn.cc:128
void * MEM_mallocN_aligned(size_t len, size_t alignment, const char *str)
Definition mallocn.cc:138
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
size_t(* MEM_allocN_len)(const void *vmemh)
Definition mallocn.cc:36
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
#define G(x, y, z)
bool foreach_strip_adt(const AnimData &adt, blender::FunctionRef< bool(NlaStrip *)> callback)
void node_tree_blend_read_data(BlendDataReader *reader, ID *owner_id, bNodeTree *ntree)
Definition node.cc:1810
void node_tree_update_all_new(Main &main)
Definition node.cc:4918
bNodeTree ** node_tree_ptr_from_id(ID *id)
Definition node.cc:4543
bNodeTree * node_tree_from_id(ID *id)
Definition node.cc:4568
MatBase< float, 3, 3 > float3x3
AllocStringStorage< keyT, hashT > & alloc_string_storage_get(const std::string &storage_identifier)
const char * name
static int lib_link_cb(LibraryIDLinkCallbackData *cb_data)
Definition readfile.cc:3671
static BHead * find_bhead(FileData *fd, void *old)
Definition readfile.cc:4466
static void * newdataadr_no_us(FileData *fd, const void *adr)
Definition readfile.cc:1507
static void long_id_names_ensure_unique_id_names(Main *bmain)
Definition readfile.cc:964
void * blo_do_versions_newlibadr(FileData *fd, ID *self_id, const bool is_linked_only, const void *adr)
Definition readfile.cc:1523
static void lib_link_scenes_check_set(Main *bmain)
Definition readfile.cc:2444
static void read_file_version_and_colorspace(FileData *fd, Main *main)
Definition readfile.cc:472
void BLO_read_struct_list_with_size(BlendDataReader *reader, const size_t expected_elem_size, ListBase *list)
Definition readfile.cc:5749
static void link_glob_list(FileData *fd, ListBase *lb)
Definition readfile.cc:1957
static ID * read_id_struct(FileData *fd, BHead *bh, const char *blockname, const int id_type_index)
Definition readfile.cc:1928
static ID * create_placeholder(Main *mainvar, const short idcode, const char *idname, const int tag, const bool was_liboverride)
Definition readfile.cc:2603
static void lib_link_all(FileData *fd, Main *bmain)
Definition readfile.cc:3699
void blo_cache_storage_end(FileData *fd)
Definition readfile.cc:1754
void blo_join_main(Main *bmain)
Definition readfile.cc:359
static void long_id_names_process_action_slots_identifiers(Main *bmain)
Definition readfile.cc:1006
static FileData * filedata_new(BlendFileReadReport *reports)
Definition readfile.cc:1119
void BLO_read_int32_array(BlendDataReader *reader, const int64_t array_size, int32_t **ptr_p)
Definition readfile.cc:5795
BlendThumbnail * BLO_thumbnail_from_file(const char *filepath)
Definition readfile.cc:1456
static void expand_main(void *fdhandle, Main *mainvar, BLOExpandDoitCallback callback)
Definition readfile.cc:4938
static void direct_link_library(FileData *fd, Library *lib, Main *main)
Definition readfile.cc:2485
static void read_file_bhead_idname_map_create(FileData *fd)
Definition readfile.cc:529
static int direct_link_id_restore_recalc_exceptions(const ID *id_current)
Definition readfile.cc:2141
void BLO_read_uint8_array(BlendDataReader *reader, const int64_t array_size, uint8_t **ptr_p)
Definition readfile.cc:5776
static void convert_pointer_array_32_to_64(BlendDataReader *, const int64_t array_size, const uint32_t *src, uint64_t *dst)
Definition readfile.cc:5869
static void split_libdata(ListBase *lb_src, blender::Vector< Main * > &lib_main_array, const bool do_split_packed_ids)
Definition readfile.cc:393
const char * blo_bhead_id_name(FileData *fd, const BHead *bhead)
Definition readfile.cc:784
void BLO_library_link_params_init(LibraryLink_Params *params, Main *bmain, const int flag, const int id_tag_extra)
Definition readfile.cc:5105
static void split_main_newid(Main *mainptr, Main *main_newid)
Definition readfile.cc:5141
void BLO_read_float_array(BlendDataReader *reader, const int64_t array_size, float **ptr_p)
Definition readfile.cc:5809
static void link_global(FileData *fd, BlendFileData *bfd)
Definition readfile.cc:3477
static BHead * read_global(BlendFileData *bfd, FileData *fd, BHead *bhead)
Definition readfile.cc:3423
int BLO_read_fileversion_get(BlendDataReader *reader)
Definition readfile.cc:5744
BHead * blo_bhead_next(FileData *fd, BHead *thisblock)
Definition readfile.cc:713
void BLO_read_uint32_array(BlendDataReader *reader, const int64_t array_size, uint32_t **ptr_p)
Definition readfile.cc:5802
blender::ImplicitSharingInfoAndData blo_read_shared_impl(BlendDataReader *reader, const void **ptr_p, const blender::FunctionRef< const blender::ImplicitSharingInfo *()> read_fn)
Definition readfile.cc:5920
static void read_undo_reuse_noundo_local_ids(FileData *fd)
Definition readfile.cc:2844
BlendFileReadReport * BLO_read_data_reports(BlendDataReader *reader)
Definition readfile.cc:5978
static const IDHash * blo_bhead_id_deep_hash(const FileData *fd, const BHead *bhead)
Definition readfile.cc:816
BHead * blo_bhead_first(FileData *fd)
Definition readfile.cc:685
static bool read_libblock_is_identical(FileData *fd, BHead *bhead)
Definition readfile.cc:2816
static void change_ID_pointer_to_real_ID_pointer_fd(FileData *fd, const void *old, void *newp)
Definition readfile.cc:1550
Main * BLO_read_lib_get_main(BlendLibReader *reader)
Definition readfile.cc:5988
static int direct_link_id_restore_recalc(const FileData *fd, const ID *id_target, const ID *id_current, const bool is_identical)
Definition readfile.cc:2152
static bool blo_bhead_is_id(const BHead *bhead)
Definition readfile.cc:512
static void direct_link_id_override_property(BlendDataReader *reader, IDOverrideLibraryProperty *op)
Definition readfile.cc:2051
static const char * library_parent_filepath(Library *lib)
Definition readfile.cc:241
static void direct_link_id_common(BlendDataReader *reader, Library *current_library, ID *id, ID *id_old, int id_tag, ID_Readfile_Data::Tags id_read_tags)
Definition readfile.cc:2248
static void direct_link_id_embedded_id(BlendDataReader *reader, Library *current_library, ID *id, ID *id_old)
Definition readfile.cc:2075
static bool oldnewmap_insert(OldNewMap *onm, const void *oldaddr, void *newaddr, const int nr)
Definition readfile.cc:272
void BLO_read_glob_list(BlendDataReader *reader, ListBase *list)
Definition readfile.cc:5973
static int has_linked_ids_to_read(Main *mainvar)
Definition readfile.cc:5326
static BHead * blo_bhead_read_full(FileData *fd, BHead *thisblock)
Definition readfile.cc:767
static void do_versions_userdef(FileData *, BlendFileData *bfd)
Definition readfile.cc:3500
static void library_link_end(Main *mainl, FileData **fd, const int flag, ReportList *reports)
Definition readfile.cc:5165
void blo_do_versions_oldnewmap_insert(OldNewMap *onm, const void *oldaddr, void *newaddr, const int nr)
Definition readfile.cc:286
static void add_main_to_main(Main *mainvar, Main *from)
Definition readfile.cc:345
static OldNewMap * oldnewmap_new()
Definition readfile.cc:263
static Main * blo_add_main_for_library(FileData *fd, Library *lib, Library *reference_lib, const char *lib_filepath, char(&filepath_abs)[FILE_MAX], const bool is_packed_library)
Definition readfile.cc:2738
static void after_liblink_id_process(BlendLibReader *reader, ID *id)
Definition readfile.cc:2038
bool BLO_read_data_is_undo(BlendDataReader *reader)
Definition readfile.cc:5963
static bool read_libblock_undo_restore_linked(FileData *fd, Main *libmain, const ID *id, ID **r_id_old, BHead *bhead)
Definition readfile.cc:2970
static void * newdataadr(FileData *fd, const void *adr)
Definition readfile.cc:1501
void * BLO_read_get_new_data_address_no_us(BlendDataReader *reader, const void *old_address, const size_t expected_size)
Definition readfile.cc:5703
static void do_versions_after_linking(FileData *fd, Main *main)
Definition readfile.cc:3608
static void read_library_clear_weak_links(FileData *basefd, Main *mainvar)
Definition readfile.cc:5467
void BLO_library_link_end(Main *mainl, BlendHandle **bh, const LibraryLink_Params *params, ReportList *reports)
Definition readfile.cc:5293
static BHead * read_data_into_datamap(FileData *fd, BHead *bhead, const char *allocname, const int id_type_index)
Definition readfile.cc:2707
static void change_link_placeholder_to_real_ID_pointer(FileData *basefd, void *old, void *newp)
Definition readfile.cc:1573
ID * BLO_read_get_new_id_address(BlendLibReader *reader, ID *self_id, const bool is_linked_only, ID *id)
Definition readfile.cc:5731
static void readfile_id_runtime_data_ensure(ID &id)
Definition readfile.cc:2198
static void read_libraries_report_invalid_id_names(FileData *fd, ReportList *reports, const bool has_forward_compatibility_issues, const char *filepath)
Definition readfile.cc:4562
static BHead * find_bhead_from_idname(FileData *fd, const char *idname)
Definition readfile.cc:4509
static void blo_cache_storage_entry_restore_in_new(ID *id, const IDCacheKey *key, void **cache_p, const uint flags, void *cache_storage_v)
Definition readfile.cc:1632
BlendFileReadReport * BLO_read_lib_reports(BlendLibReader *reader)
Definition readfile.cc:5993
AssetMetaData * blo_bhead_id_asset_data_address(const FileData *fd, const BHead *bhead)
Definition readfile.cc:808
BlendFileData * blo_read_file_internal(FileData *fd, const char *filepath)
Definition readfile.cc:3978
void BLO_readfile_id_runtime_data_free(ID &id)
Definition readfile.cc:2220
static BHead * read_libblock(FileData *fd, Main *main, BHead *bhead, int id_tag, ID_Readfile_Data::Tags id_read_tags, const bool placeholder_set_indirect_extern, ID **r_id)
Definition readfile.cc:3256
static void read_libraries(FileData *basefd)
Definition readfile.cc:5572
static void sort_bhead_old_map(FileData *fd)
Definition readfile.cc:4425
static Main * blo_find_main_for_library_and_idname(FileData *fd, const char *lib_filepath, const char *relabase, const BHead *id_bhead, const char *id_name, const bool is_packed_id)
Definition readfile.cc:4611
FileData * blo_filedata_from_memfile(MemFile *memfile, const BlendFileReadParams *params, BlendFileReadReport *reports)
Definition readfile.cc:1382
void BLO_read_double_array(BlendDataReader *reader, const int64_t array_size, double **ptr_p)
Definition readfile.cc:5821
static void fix_relpaths_library(const char *basepath, Main *main)
Definition readfile.cc:2569
static bool read_libblock_undo_restore(FileData *fd, Main *main, BHead *bhead, const int id_tag, ID **r_id_old)
Definition readfile.cc:3151
static void convert_pointer_array_64_to_32(BlendDataReader *reader, const int64_t array_size, const uint64_t *src, uint32_t *dst)
Definition readfile.cc:5857
void BLO_read_int16_array(BlendDataReader *reader, const int64_t array_size, int16_t **ptr_p)
Definition readfile.cc:5788
bool BLO_read_lib_is_undo(BlendLibReader *reader)
Definition readfile.cc:5983
void * BLO_read_struct_array_with_size(BlendDataReader *reader, const void *old_address, const size_t expected_size)
Definition readfile.cc:5711
static const void * peek_struct_undo(FileData *fd, BHead *bhead)
Definition readfile.cc:1950
static FileData * read_library_file_data(FileData *basefd, Main *bmain, Main *lib_bmain)
Definition readfile.cc:5493
static void * oldnewmap_liblookup(OldNewMap *onm, const void *addr, const bool is_linked_only)
Definition readfile.cc:307
static void oldnewmap_free(OldNewMap *onm)
Definition readfile.cc:334
static void oldnewmap_lib_insert(FileData *fd, const void *oldaddr, ID *newaddr, const int id_code)
Definition readfile.cc:281
void * BLO_read_struct_by_name_array(BlendDataReader *reader, const char *struct_name, const int64_t items_num, const void *old_address)
Definition readfile.cc:5719
static void read_id_in_lib(FileData *fd, std::queue< ID * > &ids_to_expand, Main *libmain, Library *parent_lib, BHead *bhead, ID *existing_id, ID_Readfile_Data::Tags id_read_tags)
Definition readfile.cc:4717
static void blo_cache_storage_entry_clear_in_old(ID *, const IDCacheKey *key, void **cache_p, const uint, void *cache_storage_v)
Definition readfile.cc:1667
static BHeadN * get_bhead(FileData *fd)
Definition readfile.cc:592
static ID * link_named_part(Main *mainl, FileData *fd, const short idcode, const char *name, const int flag)
Definition readfile.cc:4986
static void after_liblink_merged_bmain_process(Main *bmain, BlendFileReadReport *reports)
Definition readfile.cc:3771
void BLO_read_string(BlendDataReader *reader, char **ptr_p)
Definition readfile.cc:5828
void BLO_read_data_globmap_add(BlendDataReader *reader, void *oldaddr, void *newaddr)
Definition readfile.cc:5968
static void read_library_linked_ids(FileData *basefd, FileData *fd, Main *mainvar)
Definition readfile.cc:5398
ID_Readfile_Data::Tags BLO_readfile_id_runtime_tags(ID &id)
Definition readfile.cc:2206
static int expand_cb(LibraryIDLinkCallbackData *cb_data)
Definition readfile.cc:4900
static void read_undo_remap_noundo_data(FileData *fd)
Definition readfile.cc:3940
FileData * blo_filedata_from_file(const char *filepath, BlendFileReadReport *reports)
Definition readfile.cc:1320
void BLO_read_int8_array(BlendDataReader *reader, const int64_t array_size, int8_t **ptr_p)
Definition readfile.cc:5782
static void read_library_linked_id(FileData *basefd, FileData *fd, Main *mainvar, ID *id, ID **r_id)
Definition readfile.cc:5343
static void do_versions(FileData *fd, Library *lib, Main *main)
Definition readfile.cc:3511
static const char * get_alloc_name(FileData *fd, BHead *bh, const char *blockname, const int id_type_index=INDEX_ID_NULL)
Definition readfile.cc:1776
FileData * blo_filedata_from_memory(const void *mem, const int memsize, BlendFileReadReport *reports)
Definition readfile.cc:1350
#define BHEADN_FROM_BHEAD(bh)
Definition readfile.cc:206
static void change_link_placeholder_to_real_ID_pointer_fd(FileData *fd, const void *old, void *newp)
Definition readfile.cc:1532
Main * BLO_library_link_begin(BlendHandle **bh, const char *filepath, const LibraryLink_Params *params)
Definition readfile.cc:5133
static ID * library_id_is_yet_read(FileData *fd, Main *mainvar, BHead *bhead)
Definition readfile.cc:4549
static FileData * blo_filedata_from_file_descriptor(const char *filepath, BlendFileReadReport *reports, const int filedes)
Definition readfile.cc:1234
static ID * library_id_is_yet_read_main(Main *mainvar, const char *idname)
Definition readfile.cc:4535
static void direct_link_keymapitem(BlendDataReader *reader, wmKeyMapItem *kmi)
Definition readfile.cc:3805
static void blo_cache_storage_entry_register(ID *id, const IDCacheKey *key, void **cache_p, uint, void *cache_storage_v)
Definition readfile.cc:1612
static void * newlibadr(FileData *fd, ID *, const bool is_linked_only, const void *adr)
Definition readfile.cc:1518
static int verg_bheadsort(const void *v1, const void *v2)
Definition readfile.cc:4411
void BLO_library_link_params_init_with_context(LibraryLink_Params *params, Main *bmain, const int flag, const int id_tag_extra, Scene *scene, ViewLayer *view_layer, const View3D *v3d)
Definition readfile.cc:5116
static bool read_file_dna(FileData *fd, const char **r_error_message)
Definition readfile.cc:858
void blo_do_versions_key_uidgen(Key *key)
Definition readfile.cc:2394
static void placeholders_ensure_valid(Main *bmain)
Definition readfile.cc:2643
static BHead * find_bhead_from_code_name(FileData *fd, const short idcode, const char *name)
Definition readfile.cc:4500
void blo_cache_storage_init(FileData *fd, Main *bmain)
Definition readfile.cc:1691
void blo_make_old_idmap_from_main(FileData *fd, Main *bmain)
Definition readfile.cc:1593
short BLO_version_from_file(const char *filepath)
Definition readfile.cc:1483
BHead * blo_read_asset_data_block(FileData *fd, BHead *bhead, AssetMetaData **r_asset_data)
Definition readfile.cc:3400
static void read_libblock_undo_restore_identical(FileData *fd, Main *main, const ID *, ID *id_old, BHead *bhead, const int id_tag)
Definition readfile.cc:3016
static FileData * blo_filedata_from_file_minimal(const char *filepath)
Definition readfile.cc:1336
static ID * library_id_is_yet_read_deep_hash(FileData *fd, BHead *bhead)
Definition readfile.cc:4525
static void oldnewmap_clear(OldNewMap *onm)
Definition readfile.cc:323
static void expand_doit_library(void *fdhandle, std::queue< ID * > &ids_to_expand, Main *mainvar, void *old)
Definition readfile.cc:4785
void BLO_readfile_id_runtime_data_free_all(Main &bmain)
Definition readfile.cc:2225
static void read_libblock_undo_restore_at_old_address(FileData *fd, Main *main, ID *id, ID *id_old)
Definition readfile.cc:3084
void blo_split_main(Main *bmain, const bool do_split_packed_ids)
Definition readfile.cc:415
static bool direct_link_id(FileData *fd, Main *main, const int tag, const ID_Readfile_Data::Tags id_read_tags, ID *id, ID *id_old)
Definition readfile.cc:2655
static BHead * find_previous_lib(FileData *fd, BHead *bhead)
Definition readfile.cc:4450
#define BHEAD_USE_READ_ON_DEMAND(bhead)
Definition readfile.cc:212
void BLO_read_char_array(BlendDataReader *reader, const int64_t array_size, char **ptr_p)
Definition readfile.cc:5770
void * BLO_library_read_struct(FileData *fd, BHead *bh, const char *blockname)
Definition readfile.cc:5315
void BLO_read_float3_array(BlendDataReader *reader, const int64_t array_size, float **ptr_p)
Definition readfile.cc:5816
short blo_bhead_id_flag(const FileData *fd, const BHead *bhead)
Definition readfile.cc:798
static bool is_minversion_older_than_blender(FileData *fd, ReportList *reports)
Definition readfile.cc:1142
static void change_ID_pointer_to_real_ID_pointer(FileData *basefd, void *old, void *newp)
Definition readfile.cc:1583
ID * BLO_read_get_new_id_address_from_session_uid(BlendLibReader *reader, const uint session_uid)
Definition readfile.cc:5739
void * BLO_read_get_new_data_address(BlendDataReader *reader, const void *old_address)
Definition readfile.cc:5698
ID_Readfile_Data::Tags & BLO_readfile_id_runtime_tags_for_write(ID &id)
Definition readfile.cc:2214
static bool read_libblock_undo_restore_library(FileData *fd, const ID *id, ID *id_old, BHead *bhead)
Definition readfile.cc:2914
static void library_filedata_release(Library *lib)
Definition readfile.cc:2470
static Main * library_link_begin(Main *mainvar, FileData *fd, const char *filepath, const int id_tag_extra)
Definition readfile.cc:5058
static void blo_read_file_checks(Main *bmain)
Definition readfile.cc:3962
ID * BLO_library_link_named_part(Main *mainl, BlendHandle **bh, const short idcode, const char *name, const LibraryLink_Params *params)
Definition readfile.cc:5037
static bool blo_bhead_read_data(FileData *fd, BHead *thisblock, void *buf)
Definition readfile.cc:740
static BHead * read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead)
Definition readfile.cc:3813
void blo_filedata_free(FileData *fd)
Definition readfile.cc:1399
static int * read_file_thumbnail(FileData *fd)
Definition readfile.cc:918
static bool blo_bhead_is_id_valid_type(const BHead *bhead)
Definition readfile.cc:519
static void * blo_verify_data_address(FileData *fd, void *new_address, const void *, const size_t expected_size)
Definition readfile.cc:5674
static void after_liblink_id_embedded_id_process(BlendLibReader *reader, ID *id)
Definition readfile.cc:1994
static FileData * change_ID_link_filedata_get(Main *bmain, FileData *basefd)
Definition readfile.cc:1563
BHead * blo_bhead_prev(FileData *, BHead *thisblock)
Definition readfile.cc:705
void BLO_read_pointer_array(BlendDataReader *reader, const int64_t array_size, void **ptr_p)
Definition readfile.cc:5880
void blo_readfile_invalidate(FileData *fd, Main *bmain, const char *message)
Definition readfile.cc:556
static void read_blender_header(FileData *fd)
Definition readfile.cc:830
static void * oldnewmap_lookup_and_inc(OldNewMap *onm, const void *addr, const bool increase_users)
Definition readfile.cc:294
void blo_cache_storage_old_bmain_clear(FileData *fd, Main *bmain_old)
Definition readfile.cc:1727
static CLG_LogRef LOG_UNDO
Definition readfile.cc:183
static FileData * blo_filedata_from_file_open(const char *filepath, BlendFileReadReport *reports)
Definition readfile.cc:1305
static int read_undo_remap_noundo_data_cb(LibraryIDLinkCallbackData *cb_data)
Definition readfile.cc:3918
static void * read_struct(FileData *fd, BHead *bh, const char *blockname, const int id_type_index)
Definition readfile.cc:1853
static FileData * blo_decode_and_check(FileData *fd, ReportList *reports)
Definition readfile.cc:1188
void BLO_reportf_wrap(BlendFileReadReport *reports, const eReportType type, const char *format,...)
Definition readfile.cc:218
void * blo_read_get_new_globaldata_address(FileData *fd, const void *adr)
Definition readfile.cc:1512
static void read_undo_move_libmain_data(FileData *fd, Main *libmain, BHead *bhead)
Definition readfile.cc:2878
void(*)(void *fdhandle, std::queue< ID * > &ids_to_expand, Main *mainvar, void *idv) BLOExpandDoitCallback
Definition readfile.cc:4593
void blo_do_versions_400(FileData *fd, Library *lib, Main *bmain)
void blo_do_versions_300(FileData *fd, Library *lib, Main *bmain)
void do_versions_after_linking_450(FileData *fd, Main *bmain)
void do_versions_after_linking_300(FileData *fd, Main *bmain)
void blo_do_versions_dna(SDNA *sdna, int versionfile, int subversionfile)
void blo_do_versions_450(FileData *fd, Library *lib, Main *bmain)
void do_versions_after_linking_500(FileData *fd, Main *bmain)
void do_versions_after_linking_410(FileData *fd, Main *bmain)
void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain)
void blo_do_versions_410(FileData *fd, Library *lib, Main *bmain)
void do_versions_after_linking_400(FileData *fd, Main *bmain)
void do_versions_after_linking_430(FileData *fd, Main *bmain)
void do_versions_after_linking_250(Main *bmain)
void do_versions_after_linking_290(FileData *fd, Main *bmain)
@ FD_FLAGS_FILE_POINTSIZE_IS_4
Definition readfile.hh:50
@ FD_FLAGS_POINTSIZE_DIFFERS
Definition readfile.hh:51
@ FD_FLAGS_IS_MEMFILE
Definition readfile.hh:53
@ FD_FLAGS_FILE_OK
Definition readfile.hh:52
@ FD_FLAGS_SWITCH_ENDIAN
Definition readfile.hh:49
@ FD_FLAGS_FILE_FUTURE
Definition readfile.hh:58
@ FD_FLAGS_HAS_INVALID_ID_NAMES
Definition readfile.hh:63
void do_versions_after_linking_440(FileData *fd, Main *bmain)
void do_versions_after_linking_420(FileData *fd, Main *bmain)
void blo_do_versions_userdef(UserDef *userdef)
void blo_do_versions_500(FileData *fd, Library *lib, Main *bmain)
void blo_do_versions_420(FileData *fd, Library *lib, Main *bmain)
void do_versions_after_linking_280(FileData *fd, Main *bmain)
void blo_do_versions_290(FileData *fd, Library *lib, Main *bmain)
void blo_do_versions_270(FileData *fd, Library *lib, Main *bmain)
void do_versions_after_linking_270(Main *bmain)
void blo_do_versions_440(FileData *fd, Library *lib, Main *bmain)
void blo_do_versions_430(FileData *fd, Library *lib, Main *bmain)
void do_versions_after_linking_260(Main *bmain)
void blo_do_versions_260(FileData *fd, Library *lib, Main *bmain)
void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain)
void blo_do_versions_280(FileData *fd, Library *lib, Main *bmain)
char identifier[258]
char tmp_last_slot_identifier[258]
char last_slot_identifier[258]
The meta-data of an asset. By creating and giving this for a data-block (ID.asset_data),...
off64_t file_offset
Definition readfile.cc:198
bool has_data
Definition readfile.cc:200
BHeadN * prev
Definition readfile.cc:195
bool is_memchunk_identical
Definition readfile.cc:202
BHead bhead
Definition readfile.cc:203
BHeadN * next
Definition readfile.cc:195
const void * old
Definition readfile.cc:4408
BHead * bhead
Definition readfile.cc:4407
int64_t len
int64_t nr
const void * old
MemArena * memarena
Definition readfile.cc:1603
GHash * cache_map
Definition readfile.cc:1602
blender::Map< uint64_t, blender::ImplicitSharingInfoAndData > shared_data_by_stored_address
Definition readfile.cc:584
FileData * fd
Definition readfile.cc:578
FileData * fd
Definition readfile.cc:4599
BLOExpandDoitCallback callback
Definition readfile.cc:4602
std::queue< ID * > ids_to_expand
Definition readfile.cc:4600
UserDef * user
ViewLayer * cur_view_layer
char filepath[1024]
eBlenFileType type
bScreen * curscreen
struct BlendFileReadReport::@077003321007012203371307366200326111253233132273 duration
struct BlendFileReadReport::@124362246150331065306145367225174223236260272332 count
FileData * fd
Definition readfile.cc:588
char rect[0]
Definition BKE_main.hh:53
BHeadType bhead_type() const
eBLOReadSkip skip_flags
Definition readfile.hh:130
int undo_direction
Definition readfile.hh:93
int id_asset_data_offset
Definition readfile.hh:122
enum eFileDataFlag flags
Definition readfile.hh:81
ListBase bhead_list
Definition readfile.hh:80
int fileversion
Definition readfile.hh:111
BlenderHeader blender_header
Definition readfile.hh:83
void * storage_handle
Definition readfile.hh:195
int fileflags
Definition readfile.hh:127
DNA_ReconstructInfo * reconstruct_info
Definition readfile.hh:109
BHeadSort * bheadmap
Definition readfile.hh:154
std::optional< blender::Map< blender::StringRefNull, BHead * > > bhead_idname_map
Definition readfile.hh:157
IDNameLib_Map * new_idmap_uid
Definition readfile.hh:190
Main * old_bmain
Definition readfile.hh:168
OldNewMap * globmap
Definition readfile.hh:141
OldNewMap * datamap
Definition readfile.hh:140
int filesubversion
Definition readfile.hh:116
int id_tag_extra
Definition readfile.hh:138
FileReader * file
Definition readfile.hh:85
char relabase[FILE_MAX]
Definition readfile.hh:102
const char * compflags
Definition readfile.hh:108
BLOCacheStorage * cache_storage
Definition readfile.hh:152
std::shared_ptr< blender::Map< IDHash, ID * > > id_by_deep_hash
Definition readfile.hh:143
int globalf
Definition readfile.hh:126
Main * bmain
Definition readfile.hh:166
int id_name_offset
Definition readfile.hh:119
OldNewMap * libmap
Definition readfile.hh:150
BlendFileReadReport * reports
Definition readfile.hh:192
Main * fd_bmain
Definition readfile.hh:175
bool is_eof
Definition readfile.hh:82
int tot_bheadmap
Definition readfile.hh:155
const SDNA * memsdna
Definition readfile.hh:106
IDNameLib_Map * old_idmap_uid
Definition readfile.hh:180
SDNA * filesdna
Definition readfile.hh:105
int id_deep_hash_offset
Definition readfile.hh:124
int id_flag_offset
Definition readfile.hh:123
std::optional< BLI_stat_t > file_stat
Definition readfile.hh:86
struct ViewLayer * cur_view_layer
struct Scene * curscene
float colorspace_scene_linear_to_xyz[3][3]
uint64_t build_commit_timestamp
char colorspace_scene_linear_name[64]
struct bScreen * curscreen
char filepath[1024]
FileReaderSeekFn seek
off64_t offset
FileReaderCloseFn close
FileReaderReadFn read
unsigned int id_session_uid
Definition BKE_idtype.hh:77
ListBase properties
Definition DNA_ID.h:336
IDTypeBlendReadUndoPreserve blend_read_undo_preserve
short id_code
const char * name
IDTypeForeachCacheFunction foreach_cache
IDTypeBlendReadDataFunction blend_read_data
uint32_t flags
AssetTypeInfo * asset_type_info
IDTypeBlendReadAfterLiblinkFunction blend_read_after_liblink
Definition DNA_ID.h:414
unsigned int recalc_after_undo_push
Definition DNA_ID.h:456
unsigned int recalc
Definition DNA_ID.h:445
int tag
Definition DNA_ID.h:442
ID_RuntimeHandle * runtime
Definition DNA_ID.h:538
struct AssetMetaData * asset_data
Definition DNA_ID.h:423
struct Library * lib
Definition DNA_ID.h:420
char name[258]
Definition DNA_ID.h:432
IDProperty * system_properties
Definition DNA_ID.h:489
int us
Definition DNA_ID.h:443
int icon_id
Definition DNA_ID.h:444
struct ID * newid
Definition DNA_ID.h:418
void * prev
Definition DNA_ID.h:417
IDProperty * properties
Definition DNA_ID.h:480
IDOverrideLibrary * override_library
Definition DNA_ID.h:494
struct ID * orig_id
Definition DNA_ID.h:501
short flag
Definition DNA_ID.h:438
IDHash deep_hash
Definition DNA_ID.h:474
unsigned int recalc_up_to_undo_push
Definition DNA_ID.h:455
unsigned int session_uid
Definition DNA_ID.h:462
struct LibraryWeakReference * library_weak_reference
Definition DNA_ID.h:526
int uidgen
ListBase block
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
void * last
void * first
char scene_linear_name[64]
Definition BKE_main.hh:150
blender::float3x3 scene_linear_to_xyz
Definition BKE_main.hh:151
ListBase scenes
Definition BKE_main.hh:278
ListBase wm
Definition BKE_main.hh:307
short subversionfile
Definition BKE_main.hh:182
bool is_asset_edit_file
Definition BKE_main.hh:199
bool has_forward_compatibility_issues
Definition BKE_main.hh:192
char filepath[1024]
Definition BKE_main.hh:179
BlendThumbnail * blen_thumb
Definition BKE_main.hh:259
short minversionfile
Definition BKE_main.hh:184
uint64_t build_commit_timestamp
Definition BKE_main.hh:202
ListBase libraries
Definition BKE_main.hh:279
IDNameLib_Map * id_map
Definition BKE_main.hh:332
char build_hash[16]
Definition BKE_main.hh:204
short minsubversionfile
Definition BKE_main.hh:185
short versionfile
Definition BKE_main.hh:181
bool is_read_invalid
Definition BKE_main.hh:231
Library * curlib
Definition BKE_main.hh:269
std::shared_ptr< blender::VectorSet< Main * > > split_mains
Definition BKE_main.hh:166
MainColorspace colorspace
Definition BKE_main.hh:274
ListBase objects
Definition BKE_main.hh:280
blender::Map< uint64_t, blender::ImplicitSharingInfoAndData > sharing_info_by_address_id
MemFileSharedStorage * shared_storage
void * newp
Definition readfile.cc:253
char last_slot_identifier[258]
ListBase constraints
struct bPose * pose
blender::Map< const void *, NewAddress > map
Definition readfile.cc:260
int pointer_size
struct Collection * master_collection
struct bNodeTree * compositing_node_group
struct Scene * set
MemFile * memfile
struct ListBase addons
ListBase script_directories
struct ListBase uistyles
struct ListBase asset_shelves_settings
struct ListBase user_keymaps
short edit_studio_light
struct ListBase themes
struct ListBase autoexec_paths
struct ListBase uifonts
struct ListBase user_keyconfig_prefs
struct ListBase extension_repos
struct ListBase user_menus
struct ListBase asset_libraries
char app_template[64]
UserDef_Runtime runtime
char name[64]
struct ActionSlot ** slot_array
ListBase chanbase
struct IDProperty * prop
struct PointerRNA * ptr
i
Definition text_draw.cc:230
uint len
void version_system_idprops_generate(Main *bmain)
void version_system_idprops_nodes_generate(Main *bmain)
void version_system_idprops_children_bones_generate(Main *bmain)
short do_versions_new_to_old_idcode_get(const short id_code_new)
static DynamicLibrary lib
uint8_t flag
Definition wm_window.cc:145