Blender  V2.93
readfile.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19 
24 #include "zlib.h"
25 
26 #include <ctype.h> /* for isdigit. */
27 #include <fcntl.h> /* for open flags (O_BINARY, O_RDONLY). */
28 #include <limits.h>
29 #include <stdarg.h> /* for va_start/end. */
30 #include <stddef.h> /* for offsetof. */
31 #include <stdlib.h> /* for atoi. */
32 #include <time.h> /* for gmtime. */
33 
34 #include "BLI_utildefines.h"
35 #ifndef WIN32
36 # include <unistd.h> /* for read close */
37 #else
38 # include "BLI_winstuff.h"
39 # include "winsock2.h"
40 # include <io.h> /* for open close read */
41 #endif
42 
43 /* allow readfile to use deprecated functionality */
44 #define DNA_DEPRECATED_ALLOW
45 
46 #include "DNA_anim_types.h"
47 #include "DNA_asset_types.h"
48 #include "DNA_cachefile_types.h"
49 #include "DNA_collection_types.h"
50 #include "DNA_fileglobal_types.h"
51 #include "DNA_genfile.h"
52 #include "DNA_key_types.h"
53 #include "DNA_layer_types.h"
54 #include "DNA_node_types.h"
55 #include "DNA_packedFile_types.h"
56 #include "DNA_sdna_types.h"
57 #include "DNA_sound_types.h"
58 #include "DNA_vfont_types.h"
59 #include "DNA_volume_types.h"
60 #include "DNA_workspace_types.h"
61 
62 #include "MEM_guardedalloc.h"
63 
64 #include "BLI_blenlib.h"
65 #include "BLI_endian_switch.h"
66 #include "BLI_ghash.h"
67 #include "BLI_linklist.h"
68 #include "BLI_math.h"
69 #include "BLI_memarena.h"
70 #include "BLI_mempool.h"
71 #include "BLI_mmap.h"
72 #include "BLI_threads.h"
73 
74 #include "BLT_translation.h"
75 
76 #include "BKE_anim_data.h"
77 #include "BKE_animsys.h"
78 #include "BKE_asset.h"
79 #include "BKE_collection.h"
80 #include "BKE_global.h" /* for G */
81 #include "BKE_idprop.h"
82 #include "BKE_idtype.h"
83 #include "BKE_layer.h"
84 #include "BKE_lib_id.h"
85 #include "BKE_lib_override.h"
86 #include "BKE_lib_query.h"
87 #include "BKE_main.h" /* for Main */
88 #include "BKE_main_idmap.h"
89 #include "BKE_material.h"
90 #include "BKE_modifier.h"
91 #include "BKE_node.h" /* for tree type defines */
92 #include "BKE_object.h"
93 #include "BKE_packedFile.h"
94 #include "BKE_report.h"
95 #include "BKE_scene.h"
96 #include "BKE_screen.h"
97 #include "BKE_undo_system.h"
98 #include "BKE_workspace.h"
99 
100 #include "DRW_engine.h"
101 
102 #include "DEG_depsgraph.h"
103 
104 #include "BLO_blend_defs.h"
105 #include "BLO_blend_validate.h"
106 #include "BLO_read_write.h"
107 #include "BLO_readfile.h"
108 #include "BLO_undofile.h"
109 
110 #include "SEQ_clipboard.h"
111 #include "SEQ_iterator.h"
112 #include "SEQ_modifier.h"
113 #include "SEQ_sequencer.h"
114 
115 #include "readfile.h"
116 
117 #include <errno.h>
118 
119 /* Make preferences read-only. */
120 #define U (*((const UserDef *)&U))
121 
179 #define USE_BHEAD_READ_ON_DEMAND
180 
181 /* use GHash for BHead name-based lookups (speeds up linking) */
182 #define USE_GHASH_BHEAD
183 
184 /* Use GHash for restoring pointers by name */
185 #define USE_GHASH_RESTORE_POINTER
186 
187 /* Define this to have verbose debug prints. */
188 //#define USE_DEBUG_PRINT
189 
190 #ifdef USE_DEBUG_PRINT
191 # define DEBUG_PRINTF(...) printf(__VA_ARGS__)
192 #else
193 # define DEBUG_PRINTF(...)
194 #endif
195 
196 /* local prototypes */
197 static void read_libraries(FileData *basefd, ListBase *mainlist);
198 static void *read_struct(FileData *fd, BHead *bh, const char *blockname);
199 static BHead *find_bhead_from_code_name(FileData *fd, const short idcode, const char *name);
200 static BHead *find_bhead_from_idname(FileData *fd, const char *idname);
201 static bool library_link_idcode_needs_tag_check(const short idcode, const int flag);
202 
203 typedef struct BHeadN {
204  struct BHeadN *next, *prev;
205 #ifdef USE_BHEAD_READ_ON_DEMAND
207  off64_t file_offset;
209  bool has_data;
210 #endif
212  struct BHead bhead;
214 
215 #define BHEADN_FROM_BHEAD(bh) ((BHeadN *)POINTER_OFFSET(bh, -(int)offsetof(BHeadN, bhead)))
216 
217 /* We could change this in the future, for now it's simplest if only data is delayed
218  * because ID names are used in lookup tables. */
219 #define BHEAD_USE_READ_ON_DEMAND(bhead) ((bhead)->code == DATA)
220 
228 void BLO_reportf_wrap(ReportList *reports, ReportType type, const char *format, ...)
229 {
230  char fixed_buf[1024]; /* should be long enough */
231 
232  va_list args;
233 
234  va_start(args, format);
235  vsnprintf(fixed_buf, sizeof(fixed_buf), format, args);
236  va_end(args);
237 
238  fixed_buf[sizeof(fixed_buf) - 1] = '\0';
239 
240  BKE_report(reports, type, fixed_buf);
241 
242  if (G.background == 0) {
243  printf("%s: %s\n", BKE_report_type_str(type), fixed_buf);
244  }
245 }
246 
247 /* for reporting linking messages */
248 static const char *library_parent_filepath(Library *lib)
249 {
250  return lib->parent ? lib->parent->filepath_abs : "<direct>";
251 }
252 
253 /* -------------------------------------------------------------------- */
257 typedef struct OldNew {
258  const void *oldp;
259  void *newp;
260  /* `nr` is "user count" for data, and ID code for libdata. */
261  int nr;
263 
264 typedef struct OldNewMap {
265  /* Array that stores the actual entries. */
267  int nentries;
268  /* Hashmap that stores indices into the `entries` array. */
270 
273 
274 #define ENTRIES_CAPACITY(onm) (1ll << (onm)->capacity_exp)
275 #define MAP_CAPACITY(onm) (1ll << ((onm)->capacity_exp + 1))
276 #define SLOT_MASK(onm) (MAP_CAPACITY(onm) - 1)
277 #define DEFAULT_SIZE_EXP 6
278 #define PERTURB_SHIFT 5
279 
280 /* based on the probing algorithm used in Python dicts. */
281 #define ITER_SLOTS(onm, KEY, SLOT_NAME, INDEX_NAME) \
282  uint32_t hash = BLI_ghashutil_ptrhash(KEY); \
283  uint32_t mask = SLOT_MASK(onm); \
284  uint perturb = hash; \
285  int SLOT_NAME = mask & hash; \
286  int INDEX_NAME = onm->map[SLOT_NAME]; \
287  for (;; SLOT_NAME = mask & ((5 * SLOT_NAME) + 1 + perturb), \
288  perturb >>= PERTURB_SHIFT, \
289  INDEX_NAME = onm->map[SLOT_NAME])
290 
291 static void oldnewmap_insert_index_in_map(OldNewMap *onm, const void *ptr, int index)
292 {
293  ITER_SLOTS (onm, ptr, slot, stored_index) {
294  if (stored_index == -1) {
295  onm->map[slot] = index;
296  break;
297  }
298  }
299 }
300 
302 {
303  ITER_SLOTS (onm, entry.oldp, slot, index) {
304  if (index == -1) {
305  onm->entries[onm->nentries] = entry;
306  onm->map[slot] = onm->nentries;
307  onm->nentries++;
308  break;
309  }
310  if (onm->entries[index].oldp == entry.oldp) {
311  onm->entries[index] = entry;
312  break;
313  }
314  }
315 }
316 
317 static OldNew *oldnewmap_lookup_entry(const OldNewMap *onm, const void *addr)
318 {
319  ITER_SLOTS (onm, addr, slot, index) {
320  if (index >= 0) {
321  OldNew *entry = &onm->entries[index];
322  if (entry->oldp == addr) {
323  return entry;
324  }
325  }
326  else {
327  return NULL;
328  }
329  }
330 }
331 
333 {
334  memset(onm->map, 0xFF, MAP_CAPACITY(onm) * sizeof(*onm->map));
335 }
336 
338 {
339  onm->capacity_exp++;
340  onm->entries = MEM_reallocN(onm->entries, sizeof(*onm->entries) * ENTRIES_CAPACITY(onm));
341  onm->map = MEM_reallocN(onm->map, sizeof(*onm->map) * MAP_CAPACITY(onm));
342  oldnewmap_clear_map(onm);
343  for (int i = 0; i < onm->nentries; i++) {
344  oldnewmap_insert_index_in_map(onm, onm->entries[i].oldp, i);
345  }
346 }
347 
348 /* Public OldNewMap API */
349 
351 {
352  OldNewMap *onm = MEM_callocN(sizeof(*onm), "OldNewMap");
353 
355  onm->entries = MEM_malloc_arrayN(
356  ENTRIES_CAPACITY(onm), sizeof(*onm->entries), "OldNewMap.entries");
357  onm->map = MEM_malloc_arrayN(MAP_CAPACITY(onm), sizeof(*onm->map), "OldNewMap.map");
358  oldnewmap_clear_map(onm);
359 
360  return onm;
361 }
362 
363 static void oldnewmap_insert(OldNewMap *onm, const void *oldaddr, void *newaddr, int nr)
364 {
365  if (oldaddr == NULL || newaddr == NULL) {
366  return;
367  }
368 
369  if (UNLIKELY(onm->nentries == ENTRIES_CAPACITY(onm))) {
371  }
372 
373  OldNew entry;
374  entry.oldp = oldaddr;
375  entry.newp = newaddr;
376  entry.nr = nr;
377  oldnewmap_insert_or_replace(onm, entry);
378 }
379 
380 void blo_do_versions_oldnewmap_insert(OldNewMap *onm, const void *oldaddr, void *newaddr, int nr)
381 {
382  oldnewmap_insert(onm, oldaddr, newaddr, nr);
383 }
384 
385 static void *oldnewmap_lookup_and_inc(OldNewMap *onm, const void *addr, bool increase_users)
386 {
387  OldNew *entry = oldnewmap_lookup_entry(onm, addr);
388  if (entry == NULL) {
389  return NULL;
390  }
391  if (increase_users) {
392  entry->nr++;
393  }
394  return entry->newp;
395 }
396 
397 /* for libdata, OldNew.nr has ID code, no increment */
398 static void *oldnewmap_liblookup(OldNewMap *onm, const void *addr, const void *lib)
399 {
400  if (addr == NULL) {
401  return NULL;
402  }
403 
404  ID *id = oldnewmap_lookup_and_inc(onm, addr, false);
405  if (id == NULL) {
406  return NULL;
407  }
408  if (!lib || id->lib) {
409  return id;
410  }
411  return NULL;
412 }
413 
414 static void oldnewmap_clear(OldNewMap *onm)
415 {
416  /* Free unused data. */
417  for (int i = 0; i < onm->nentries; i++) {
418  OldNew *entry = &onm->entries[i];
419  if (entry->nr == 0) {
420  MEM_freeN(entry->newp);
421  entry->newp = NULL;
422  }
423  }
424 
426  oldnewmap_clear_map(onm);
427  onm->nentries = 0;
428 }
429 
430 static void oldnewmap_free(OldNewMap *onm)
431 {
432  MEM_freeN(onm->entries);
433  MEM_freeN(onm->map);
434  MEM_freeN(onm);
435 }
436 
437 #undef ENTRIES_CAPACITY
438 #undef MAP_CAPACITY
439 #undef SLOT_MASK
440 #undef DEFAULT_SIZE_EXP
441 #undef PERTURB_SHIFT
442 #undef ITER_SLOTS
443 
446 /* -------------------------------------------------------------------- */
450 static void add_main_to_main(Main *mainvar, Main *from)
451 {
452  ListBase *lbarray[INDEX_ID_MAX], *fromarray[INDEX_ID_MAX];
453  int a;
454 
455  set_listbasepointers(mainvar, lbarray);
456  a = set_listbasepointers(from, fromarray);
457  while (a--) {
458  BLI_movelisttolist(lbarray[a], fromarray[a]);
459  }
460 }
461 
462 void blo_join_main(ListBase *mainlist)
463 {
464  Main *tojoin, *mainl;
465 
466  mainl = mainlist->first;
467  while ((tojoin = mainl->next)) {
468  add_main_to_main(mainl, tojoin);
469  BLI_remlink(mainlist, tojoin);
470  BKE_main_free(tojoin);
471  }
472 }
473 
474 static void split_libdata(ListBase *lb_src, Main **lib_main_array, const uint lib_main_array_len)
475 {
476  for (ID *id = lb_src->first, *idnext; id; id = idnext) {
477  idnext = id->next;
478 
479  if (id->lib) {
480  if (((uint)id->lib->temp_index < lib_main_array_len) &&
481  /* this check should never fail, just in case 'id->lib' is a dangling pointer. */
482  (lib_main_array[id->lib->temp_index]->curlib == id->lib)) {
483  Main *mainvar = lib_main_array[id->lib->temp_index];
484  ListBase *lb_dst = which_libbase(mainvar, GS(id->name));
485  BLI_remlink(lb_src, id);
486  BLI_addtail(lb_dst, id);
487  }
488  else {
489  printf("%s: invalid library for '%s'\n", __func__, id->name);
490  BLI_assert(0);
491  }
492  }
493  }
494 }
495 
496 void blo_split_main(ListBase *mainlist, Main *main)
497 {
498  mainlist->first = mainlist->last = main;
499  main->next = NULL;
500 
501  if (BLI_listbase_is_empty(&main->libraries)) {
502  return;
503  }
504 
505  /* (Library.temp_index -> Main), lookup table */
506  const uint lib_main_array_len = BLI_listbase_count(&main->libraries);
507  Main **lib_main_array = MEM_malloc_arrayN(lib_main_array_len, sizeof(*lib_main_array), __func__);
508 
509  int i = 0;
510  for (Library *lib = main->libraries.first; lib; lib = lib->id.next, i++) {
511  Main *libmain = BKE_main_new();
512  libmain->curlib = lib;
513  libmain->versionfile = lib->versionfile;
514  libmain->subversionfile = lib->subversionfile;
515  BLI_addtail(mainlist, libmain);
516  lib->temp_index = i;
517  lib_main_array[i] = libmain;
518  }
519 
520  ListBase *lbarray[INDEX_ID_MAX];
521  i = set_listbasepointers(main, lbarray);
522  while (i--) {
523  ID *id = lbarray[i]->first;
524  if (id == NULL || GS(id->name) == ID_LI) {
525  /* No ID_LI data-lock should ever be linked anyway, but just in case, better be explicit. */
526  continue;
527  }
528  split_libdata(lbarray[i], lib_main_array, lib_main_array_len);
529  }
530 
531  MEM_freeN(lib_main_array);
532 }
533 
535 {
536  BHead *bhead;
537 
538  for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
539  if (bhead->code == GLOB) {
540  FileGlobal *fg = read_struct(fd, bhead, "Global");
541  if (fg) {
542  main->subversionfile = fg->subversion;
543  main->minversionfile = fg->minversion;
544  main->minsubversionfile = fg->minsubversion;
545  MEM_freeN(fg);
546  }
547  else if (bhead->code == ENDB) {
548  break;
549  }
550  }
551  }
552  if (main->curlib) {
553  main->curlib->versionfile = main->versionfile;
554  main->curlib->subversionfile = main->subversionfile;
555  }
556 }
557 
558 static bool blo_bhead_is_id(const BHead *bhead)
559 {
560  /* BHead codes are four bytes (like 'ENDB', 'TEST', etc.), but if the two most-significant bytes
561  * are zero, the values actually indicate an ID type. */
562  return bhead->code <= 0xFFFF;
563 }
564 
565 static bool blo_bhead_is_id_valid_type(const BHead *bhead)
566 {
567  if (!blo_bhead_is_id(bhead)) {
568  return false;
569  }
570 
571  const short id_type_code = bhead->code & 0xFFFF;
572  return BKE_idtype_idcode_is_valid(id_type_code);
573 }
574 
575 #ifdef USE_GHASH_BHEAD
577 {
578  BHead *bhead;
579 
580  /* dummy values */
581  bool is_link = false;
582  int code_prev = ENDB;
583  uint reserve = 0;
584 
585  for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
586  if (code_prev != bhead->code) {
587  code_prev = bhead->code;
588  is_link = blo_bhead_is_id_valid_type(bhead) ?
589  BKE_idtype_idcode_is_linkable((short)code_prev) :
590  false;
591  }
592 
593  if (is_link) {
594  reserve += 1;
595  }
596  }
597 
599 
600  fd->bhead_idname_hash = BLI_ghash_str_new_ex(__func__, reserve);
601 
602  for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
603  if (code_prev != bhead->code) {
604  code_prev = bhead->code;
605  is_link = blo_bhead_is_id_valid_type(bhead) ?
606  BKE_idtype_idcode_is_linkable((short)code_prev) :
607  false;
608  }
609 
610  if (is_link) {
611  BLI_ghash_insert(fd->bhead_idname_hash, (void *)blo_bhead_id_name(fd, bhead), bhead);
612  }
613  }
614 }
615 #endif
616 
617 static Main *blo_find_main(FileData *fd, const char *filepath, const char *relabase)
618 {
619  ListBase *mainlist = fd->mainlist;
620  Main *m;
621  Library *lib;
622  char name1[FILE_MAX];
623 
624  BLI_strncpy(name1, filepath, sizeof(name1));
625  BLI_path_normalize(relabase, name1);
626 
627  // printf("blo_find_main: relabase %s\n", relabase);
628  // printf("blo_find_main: original in %s\n", filepath);
629  // printf("blo_find_main: converted to %s\n", name1);
630 
631  for (m = mainlist->first; m; m = m->next) {
632  const char *libname = (m->curlib) ? m->curlib->filepath_abs : m->name;
633 
634  if (BLI_path_cmp(name1, libname) == 0) {
635  if (G.debug & G_DEBUG) {
636  printf("blo_find_main: found library %s\n", libname);
637  }
638  return m;
639  }
640  }
641 
642  m = BKE_main_new();
643  BLI_addtail(mainlist, m);
644 
645  /* Add library data-block itself to 'main' Main, since libraries are **never** linked data.
646  * Fixes bug where you could end with all ID_LI data-blocks having the same name... */
647  lib = BKE_libblock_alloc(mainlist->first, ID_LI, BLI_path_basename(filepath), 0);
648 
649  /* Important, consistency with main ID reading code from read_libblock(). */
650  lib->id.us = ID_FAKE_USERS(lib);
651 
652  /* Matches direct_link_library(). */
653  id_us_ensure_real(&lib->id);
654 
655  BLI_strncpy(lib->filepath, filepath, sizeof(lib->filepath));
656  BLI_strncpy(lib->filepath_abs, name1, sizeof(lib->filepath_abs));
657 
658  m->curlib = lib;
659 
660  read_file_version(fd, m);
661 
662  if (G.debug & G_DEBUG) {
663  printf("blo_find_main: added new lib %s\n", filepath);
664  }
665  return m;
666 }
667 
670 /* -------------------------------------------------------------------- */
674 typedef struct BlendDataReader {
677 
678 typedef struct BlendLibReader {
682 
683 typedef struct BlendExpander {
687 
688 static void switch_endian_bh4(BHead4 *bhead)
689 {
690  /* the ID_.. codes */
691  if ((bhead->code & 0xFFFF) == 0) {
692  bhead->code >>= 16;
693  }
694 
695  if (bhead->code != ENDB) {
696  BLI_endian_switch_int32(&bhead->len);
698  BLI_endian_switch_int32(&bhead->nr);
699  }
700 }
701 
702 static void switch_endian_bh8(BHead8 *bhead)
703 {
704  /* the ID_.. codes */
705  if ((bhead->code & 0xFFFF) == 0) {
706  bhead->code >>= 16;
707  }
708 
709  if (bhead->code != ENDB) {
710  BLI_endian_switch_int32(&bhead->len);
712  BLI_endian_switch_int32(&bhead->nr);
713  }
714 }
715 
716 static void bh4_from_bh8(BHead *bhead, BHead8 *bhead8, bool do_endian_swap)
717 {
718  BHead4 *bhead4 = (BHead4 *)bhead;
719  int64_t old;
720 
721  bhead4->code = bhead8->code;
722  bhead4->len = bhead8->len;
723 
724  if (bhead4->code != ENDB) {
725  /* perform a endian swap on 64bit pointers, otherwise the pointer might map to zero
726  * 0x0000000000000000000012345678 would become 0x12345678000000000000000000000000
727  */
728  if (do_endian_swap) {
729  BLI_endian_switch_uint64(&bhead8->old);
730  }
731 
732  /* this patch is to avoid a long long being read from not-eight aligned positions
733  * is necessary on any modern 64bit architecture) */
734  memcpy(&old, &bhead8->old, 8);
735  bhead4->old = (int)(old >> 3);
736 
737  bhead4->SDNAnr = bhead8->SDNAnr;
738  bhead4->nr = bhead8->nr;
739  }
740 }
741 
742 static void bh8_from_bh4(BHead *bhead, BHead4 *bhead4)
743 {
744  BHead8 *bhead8 = (BHead8 *)bhead;
745 
746  bhead8->code = bhead4->code;
747  bhead8->len = bhead4->len;
748 
749  if (bhead8->code != ENDB) {
750  bhead8->old = bhead4->old;
751  bhead8->SDNAnr = bhead4->SDNAnr;
752  bhead8->nr = bhead4->nr;
753  }
754 }
755 
757 {
758  BHeadN *new_bhead = NULL;
759  ssize_t readsize;
760 
761  if (fd) {
762  if (!fd->is_eof) {
763  /* initializing to zero isn't strictly needed but shuts valgrind up
764  * since uninitialized memory gets compared */
765  BHead8 bhead8 = {0};
766  BHead4 bhead4 = {0};
767  BHead bhead = {0};
768 
769  /* First read the bhead structure.
770  * Depending on the platform the file was written on this can
771  * be a big or little endian BHead4 or BHead8 structure.
772  *
773  * As usual 'ENDB' (the last *partial* bhead of the file)
774  * needs some special handling. We don't want to EOF just yet.
775  */
777  bhead4.code = DATA;
778  readsize = fd->read(fd, &bhead4, sizeof(bhead4), NULL);
779 
780  if (readsize == sizeof(bhead4) || bhead4.code == ENDB) {
781  if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
782  switch_endian_bh4(&bhead4);
783  }
784 
785  if (fd->flags & FD_FLAGS_POINTSIZE_DIFFERS) {
786  bh8_from_bh4(&bhead, &bhead4);
787  }
788  else {
789  /* MIN2 is only to quiet '-Warray-bounds' compiler warning. */
790  BLI_assert(sizeof(bhead) == sizeof(bhead4));
791  memcpy(&bhead, &bhead4, MIN2(sizeof(bhead), sizeof(bhead4)));
792  }
793  }
794  else {
795  fd->is_eof = true;
796  bhead.len = 0;
797  }
798  }
799  else {
800  bhead8.code = DATA;
801  readsize = fd->read(fd, &bhead8, sizeof(bhead8), NULL);
802 
803  if (readsize == sizeof(bhead8) || bhead8.code == ENDB) {
804  if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
805  switch_endian_bh8(&bhead8);
806  }
807 
808  if (fd->flags & FD_FLAGS_POINTSIZE_DIFFERS) {
809  bh4_from_bh8(&bhead, &bhead8, (fd->flags & FD_FLAGS_SWITCH_ENDIAN) != 0);
810  }
811  else {
812  /* MIN2 is only to quiet '-Warray-bounds' compiler warning. */
813  BLI_assert(sizeof(bhead) == sizeof(bhead8));
814  memcpy(&bhead, &bhead8, MIN2(sizeof(bhead), sizeof(bhead8)));
815  }
816  }
817  else {
818  fd->is_eof = true;
819  bhead.len = 0;
820  }
821  }
822 
823  /* make sure people are not trying to pass bad blend files */
824  if (bhead.len < 0) {
825  fd->is_eof = true;
826  }
827 
828  /* bhead now contains the (converted) bhead structure. Now read
829  * the associated data and put everything in a BHeadN (creative naming !)
830  */
831  if (fd->is_eof) {
832  /* pass */
833  }
834 #ifdef USE_BHEAD_READ_ON_DEMAND
835  else if (fd->seek != NULL && BHEAD_USE_READ_ON_DEMAND(&bhead)) {
836  /* Delay reading bhead content. */
837  new_bhead = MEM_mallocN(sizeof(BHeadN), "new_bhead");
838  if (new_bhead) {
839  new_bhead->next = new_bhead->prev = NULL;
840  new_bhead->file_offset = fd->file_offset;
841  new_bhead->has_data = false;
842  new_bhead->is_memchunk_identical = false;
843  new_bhead->bhead = bhead;
844  off64_t seek_new = fd->seek(fd, bhead.len, SEEK_CUR);
845  if (seek_new == -1) {
846  fd->is_eof = true;
847  MEM_freeN(new_bhead);
848  new_bhead = NULL;
849  }
850  BLI_assert(fd->file_offset == seek_new);
851  }
852  else {
853  fd->is_eof = true;
854  }
855  }
856 #endif
857  else {
858  new_bhead = MEM_mallocN(sizeof(BHeadN) + (size_t)bhead.len, "new_bhead");
859  if (new_bhead) {
860  new_bhead->next = new_bhead->prev = NULL;
861 #ifdef USE_BHEAD_READ_ON_DEMAND
862  new_bhead->file_offset = 0; /* don't seek. */
863  new_bhead->has_data = true;
864 #endif
865  new_bhead->is_memchunk_identical = false;
866  new_bhead->bhead = bhead;
867 
868  readsize = fd->read(
869  fd, new_bhead + 1, (size_t)bhead.len, &new_bhead->is_memchunk_identical);
870 
871  if (readsize != (ssize_t)bhead.len) {
872  fd->is_eof = true;
873  MEM_freeN(new_bhead);
874  new_bhead = NULL;
875  }
876  }
877  else {
878  fd->is_eof = true;
879  }
880  }
881  }
882  }
883 
884  /* We've read a new block. Now add it to the list
885  * of blocks.
886  */
887  if (new_bhead) {
888  BLI_addtail(&fd->bhead_list, new_bhead);
889  }
890 
891  return new_bhead;
892 }
893 
895 {
896  BHeadN *new_bhead;
897  BHead *bhead = NULL;
898 
899  /* Rewind the file
900  * Read in a new block if necessary
901  */
902  new_bhead = fd->bhead_list.first;
903  if (new_bhead == NULL) {
904  new_bhead = get_bhead(fd);
905  }
906 
907  if (new_bhead) {
908  bhead = &new_bhead->bhead;
909  }
910 
911  return bhead;
912 }
913 
915 {
916  BHeadN *bheadn = BHEADN_FROM_BHEAD(thisblock);
917  BHeadN *prev = bheadn->prev;
918 
919  return (prev) ? &prev->bhead : NULL;
920 }
921 
923 {
924  BHeadN *new_bhead = NULL;
925  BHead *bhead = NULL;
926 
927  if (thisblock) {
928  /* bhead is actually a sub part of BHeadN
929  * We calculate the BHeadN pointer from the BHead pointer below */
930  new_bhead = BHEADN_FROM_BHEAD(thisblock);
931 
932  /* get the next BHeadN. If it doesn't exist we read in the next one */
933  new_bhead = new_bhead->next;
934  if (new_bhead == NULL) {
935  new_bhead = get_bhead(fd);
936  }
937  }
938 
939  if (new_bhead) {
940  /* here we do the reverse:
941  * go from the BHeadN pointer to the BHead pointer */
942  bhead = &new_bhead->bhead;
943  }
944 
945  return bhead;
946 }
947 
948 #ifdef USE_BHEAD_READ_ON_DEMAND
949 static bool blo_bhead_read_data(FileData *fd, BHead *thisblock, void *buf)
950 {
951  bool success = true;
952  BHeadN *new_bhead = BHEADN_FROM_BHEAD(thisblock);
953  BLI_assert(new_bhead->has_data == false && new_bhead->file_offset != 0);
954  off64_t offset_backup = fd->file_offset;
955  if (UNLIKELY(fd->seek(fd, new_bhead->file_offset, SEEK_SET) == -1)) {
956  success = false;
957  }
958  else {
959  if (fd->read(fd, buf, (size_t)new_bhead->bhead.len, &new_bhead->is_memchunk_identical) !=
960  (ssize_t)new_bhead->bhead.len) {
961  success = false;
962  }
963  }
964  if (fd->seek(fd, offset_backup, SEEK_SET) == -1) {
965  success = false;
966  }
967  return success;
968 }
969 
970 static BHead *blo_bhead_read_full(FileData *fd, BHead *thisblock)
971 {
972  BHeadN *new_bhead = BHEADN_FROM_BHEAD(thisblock);
973  BHeadN *new_bhead_data = MEM_mallocN(sizeof(BHeadN) + new_bhead->bhead.len, "new_bhead");
974  new_bhead_data->bhead = new_bhead->bhead;
975  new_bhead_data->file_offset = new_bhead->file_offset;
976  new_bhead_data->has_data = true;
977  new_bhead_data->is_memchunk_identical = false;
978  if (!blo_bhead_read_data(fd, thisblock, new_bhead_data + 1)) {
979  MEM_freeN(new_bhead_data);
980  return NULL;
981  }
982  return &new_bhead_data->bhead;
983 }
984 #endif /* USE_BHEAD_READ_ON_DEMAND */
985 
986 /* Warning! Caller's responsibility to ensure given bhead **is** an ID one! */
987 const char *blo_bhead_id_name(const FileData *fd, const BHead *bhead)
988 {
989  return (const char *)POINTER_OFFSET(bhead, sizeof(*bhead) + fd->id_name_offset);
990 }
991 
992 /* Warning! Caller's responsibility to ensure given bhead **is** an ID one! */
994 {
996  return (fd->id_asset_data_offset >= 0) ?
997  *(AssetMetaData **)POINTER_OFFSET(bhead, sizeof(*bhead) + fd->id_asset_data_offset) :
998  NULL;
999 }
1000 
1002 {
1003  char header[SIZEOFBLENDERHEADER], num[4];
1004  ssize_t readsize;
1005 
1006  /* read in the header data */
1007  readsize = fd->read(fd, header, sizeof(header), NULL);
1008 
1009  if (readsize == sizeof(header) && STREQLEN(header, "BLENDER", 7) && ELEM(header[7], '_', '-') &&
1010  ELEM(header[8], 'v', 'V') &&
1011  (isdigit(header[9]) && isdigit(header[10]) && isdigit(header[11]))) {
1012  fd->flags |= FD_FLAGS_FILE_OK;
1013 
1014  /* what size are pointers in the file ? */
1015  if (header[7] == '_') {
1017  if (sizeof(void *) != 4) {
1019  }
1020  }
1021  else {
1022  if (sizeof(void *) != 8) {
1024  }
1025  }
1026 
1027  /* is the file saved in a different endian
1028  * than we need ?
1029  */
1030  if (((header[8] == 'v') ? L_ENDIAN : B_ENDIAN) != ENDIAN_ORDER) {
1032  }
1033 
1034  /* get the version number */
1035  memcpy(num, header + 9, 3);
1036  num[3] = 0;
1037  fd->fileversion = atoi(num);
1038  }
1039 }
1040 
1044 static bool read_file_dna(FileData *fd, const char **r_error_message)
1045 {
1046  BHead *bhead;
1047  int subversion = 0;
1048 
1049  for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
1050  if (bhead->code == GLOB) {
1051  /* Before this, the subversion didn't exist in 'FileGlobal' so the subversion
1052  * value isn't accessible for the purpose of DNA versioning in this case. */
1053  if (fd->fileversion <= 242) {
1054  continue;
1055  }
1056  /* We can't use read_global because this needs 'DNA1' to be decoded,
1057  * however the first 4 chars are _always_ the subversion. */
1058  FileGlobal *fg = (void *)&bhead[1];
1059  BLI_STATIC_ASSERT(offsetof(FileGlobal, subvstr) == 0, "Must be first: subvstr")
1060  char num[5];
1061  memcpy(num, fg->subvstr, 4);
1062  num[4] = 0;
1063  subversion = atoi(num);
1064  }
1065  else if (bhead->code == DNA1) {
1066  const bool do_endian_swap = (fd->flags & FD_FLAGS_SWITCH_ENDIAN) != 0;
1067 
1069  &bhead[1], bhead->len, do_endian_swap, true, r_error_message);
1070  if (fd->filesdna) {
1071  blo_do_versions_dna(fd->filesdna, fd->fileversion, subversion);
1074  fd->filesdna, fd->memsdna, fd->compflags);
1075  /* used to retrieve ID names from (bhead+1) */
1076  fd->id_name_offset = DNA_elem_offset(fd->filesdna, "ID", "char", "name[]");
1077  BLI_assert(fd->id_name_offset != -1);
1079  fd->filesdna, "ID", "AssetMetaData", "*asset_data");
1080 
1081  return true;
1082  }
1083 
1084  return false;
1085  }
1086  else if (bhead->code == ENDB) {
1087  break;
1088  }
1089  }
1090 
1091  *r_error_message = "Missing DNA block";
1092  return false;
1093 }
1094 
1096 {
1097  BHead *bhead;
1098  int *blend_thumb = NULL;
1099 
1100  for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
1101  if (bhead->code == TEST) {
1102  const bool do_endian_swap = (fd->flags & FD_FLAGS_SWITCH_ENDIAN) != 0;
1103  int *data = (int *)(bhead + 1);
1104 
1105  if (bhead->len < (sizeof(int[2]))) {
1106  break;
1107  }
1108 
1109  if (do_endian_swap) {
1112  }
1113 
1114  const int width = data[0];
1115  const int height = data[1];
1117  break;
1118  }
1119  if (bhead->len < BLEN_THUMB_MEMSIZE_FILE(width, height)) {
1120  break;
1121  }
1122 
1123  blend_thumb = data;
1124  break;
1125  }
1126  if (bhead->code != REND) {
1127  /* Thumbnail is stored in TEST immediately after first REND... */
1128  break;
1129  }
1130  }
1131 
1132  return blend_thumb;
1133 }
1134 
1137 /* -------------------------------------------------------------------- */
1141 /* Regular file reading. */
1142 
1144  void *buffer,
1145  size_t size,
1146  bool *UNUSED(r_is_memchunck_identical))
1147 {
1148  ssize_t readsize = read(filedata->filedes, buffer, size);
1149 
1150  if (readsize < 0) {
1151  readsize = EOF;
1152  }
1153  else {
1154  filedata->file_offset += readsize;
1155  }
1156 
1157  return readsize;
1158 }
1159 
1160 static off64_t fd_seek_data_from_file(FileData *filedata, off64_t offset, int whence)
1161 {
1162  filedata->file_offset = BLI_lseek(filedata->filedes, offset, whence);
1163  return filedata->file_offset;
1164 }
1165 
1166 /* GZip file reading. */
1167 
1169  void *buffer,
1170  size_t size,
1171  bool *UNUSED(r_is_memchunck_identical))
1172 {
1173  BLI_assert(size <= INT_MAX);
1174 
1175  ssize_t readsize = gzread(filedata->gzfiledes, buffer, (uint)size);
1176 
1177  if (readsize < 0) {
1178  readsize = EOF;
1179  }
1180  else {
1181  filedata->file_offset += readsize;
1182  }
1183 
1184  return readsize;
1185 }
1186 
1187 /* Memory reading. */
1188 
1190  void *buffer,
1191  size_t size,
1192  bool *UNUSED(r_is_memchunck_identical))
1193 {
1194  /* don't read more bytes than there are available in the buffer */
1195  ssize_t readsize = (ssize_t)MIN2(size, filedata->buffersize - (size_t)filedata->file_offset);
1196 
1197  memcpy(buffer, filedata->buffer + filedata->file_offset, (size_t)readsize);
1198  filedata->file_offset += readsize;
1199 
1200  return readsize;
1201 }
1202 
1203 /* Memory-mapped file reading.
1204  * By using mmap(), we can map a file so that it can be treated like normal memory,
1205  * meaning that we can just read from it with memcpy() etc.
1206  * This avoids system call overhead and can significantly speed up file loading.
1207  */
1208 
1210  void *buffer,
1211  size_t size,
1212  bool *UNUSED(r_is_memchunck_identical))
1213 {
1214  /* don't read more bytes than there are available in the buffer */
1215  size_t readsize = MIN2(size, (size_t)(filedata->buffersize - filedata->file_offset));
1216 
1217  if (!BLI_mmap_read(filedata->mmap_file, buffer, filedata->file_offset, readsize)) {
1218  return 0;
1219  }
1220 
1221  filedata->file_offset += readsize;
1222 
1223  return readsize;
1224 }
1225 
1226 static off64_t fd_seek_from_mmap(FileData *filedata, off64_t offset, int whence)
1227 {
1228  off64_t new_pos;
1229  if (whence == SEEK_CUR) {
1230  new_pos = filedata->file_offset + offset;
1231  }
1232  else if (whence == SEEK_SET) {
1233  new_pos = offset;
1234  }
1235  else if (whence == SEEK_END) {
1236  new_pos = filedata->buffersize + offset;
1237  }
1238  else {
1239  return -1;
1240  }
1241 
1242  if (new_pos < 0 || new_pos > filedata->buffersize) {
1243  return -1;
1244  }
1245 
1246  filedata->file_offset = new_pos;
1247  return filedata->file_offset;
1248 }
1249 
1250 /* MemFile reading. */
1251 
1253  void *buffer,
1254  size_t size,
1255  bool *r_is_memchunck_identical)
1256 {
1257  static size_t seek = SIZE_MAX; /* the current position */
1258  static size_t offset = 0; /* size of previous chunks */
1259  static MemFileChunk *chunk = NULL;
1260  size_t chunkoffset, readsize, totread;
1261 
1262  if (r_is_memchunck_identical != NULL) {
1263  *r_is_memchunck_identical = true;
1264  }
1265 
1266  if (size == 0) {
1267  return 0;
1268  }
1269 
1270  if (seek != (size_t)filedata->file_offset) {
1271  chunk = filedata->memfile->chunks.first;
1272  seek = 0;
1273 
1274  while (chunk) {
1275  if (seek + chunk->size > (size_t)filedata->file_offset) {
1276  break;
1277  }
1278  seek += chunk->size;
1279  chunk = chunk->next;
1280  }
1281  offset = seek;
1282  seek = (size_t)filedata->file_offset;
1283  }
1284 
1285  if (chunk) {
1286  totread = 0;
1287 
1288  do {
1289  /* first check if it's on the end if current chunk */
1290  if (seek - offset == chunk->size) {
1291  offset += chunk->size;
1292  chunk = chunk->next;
1293  }
1294 
1295  /* debug, should never happen */
1296  if (chunk == NULL) {
1297  printf("illegal read, chunk zero\n");
1298  return 0;
1299  }
1300 
1301  chunkoffset = seek - offset;
1302  readsize = size - totread;
1303 
1304  /* data can be spread over multiple chunks, so clamp size
1305  * to within this chunk, and then it will read further in
1306  * the next chunk */
1307  if (chunkoffset + readsize > chunk->size) {
1308  readsize = chunk->size - chunkoffset;
1309  }
1310 
1311  memcpy(POINTER_OFFSET(buffer, totread), chunk->buf + chunkoffset, readsize);
1312  totread += readsize;
1313  filedata->file_offset += readsize;
1314  seek += readsize;
1315  if (r_is_memchunck_identical != NULL) {
1316  /* `is_identical` of current chunk represents whether it changed compared to previous undo
1317  * step. this is fine in redo case, but not in undo case, where we need an extra flag
1318  * defined when saving the next (future) step after the one we want to restore, as we are
1319  * supposed to 'come from' that future undo step, and not the one before current one. */
1320  *r_is_memchunck_identical &= filedata->undo_direction == STEP_REDO ?
1321  chunk->is_identical :
1322  chunk->is_identical_future;
1323  }
1324  } while (totread < size);
1325 
1326  return (ssize_t)totread;
1327  }
1328 
1329  return 0;
1330 }
1331 
1332 static FileData *filedata_new(void)
1333 {
1334  FileData *fd = MEM_callocN(sizeof(FileData), "FileData");
1335 
1336  fd->filedes = -1;
1337  fd->gzfiledes = NULL;
1338 
1339  fd->memsdna = DNA_sdna_current_get();
1340 
1341  fd->datamap = oldnewmap_new();
1342  fd->globmap = oldnewmap_new();
1343  fd->libmap = oldnewmap_new();
1344 
1345  return fd;
1346 }
1347 
1349 {
1351 
1352  if (fd->flags & FD_FLAGS_FILE_OK) {
1353  const char *error_message = NULL;
1354  if (read_file_dna(fd, &error_message) == false) {
1355  BKE_reportf(
1356  reports, RPT_ERROR, "Failed to read blend file '%s': %s", fd->relabase, error_message);
1357  blo_filedata_free(fd);
1358  fd = NULL;
1359  }
1360  }
1361  else {
1362  BKE_reportf(
1363  reports, RPT_ERROR, "Failed to read blend file '%s', not a blend file", fd->relabase);
1364  blo_filedata_free(fd);
1365  fd = NULL;
1366  }
1367 
1368  return fd;
1369 }
1370 
1371 static FileData *blo_filedata_from_file_descriptor(const char *filepath,
1372  ReportList *reports,
1373  int file)
1374 {
1375  FileDataReadFn *read_fn = NULL;
1376  FileDataSeekFn *seek_fn = NULL; /* Optional. */
1377  size_t buffersize = 0;
1378  BLI_mmap_file *mmap_file = NULL;
1379 
1380  gzFile gzfile = (gzFile)Z_NULL;
1381 
1382  char header[7];
1383 
1384  /* Regular file. */
1385  errno = 0;
1386  if (read(file, header, sizeof(header)) != sizeof(header)) {
1387  BKE_reportf(reports,
1388  RPT_WARNING,
1389  "Unable to read '%s': %s",
1390  filepath,
1391  errno ? strerror(errno) : TIP_("insufficient content"));
1392  return NULL;
1393  }
1394 
1395  /* Regular file. */
1396  if (memcmp(header, "BLENDER", sizeof(header)) == 0) {
1397  read_fn = fd_read_data_from_file;
1398  seek_fn = fd_seek_data_from_file;
1399 
1400  mmap_file = BLI_mmap_open(file);
1401  if (mmap_file != NULL) {
1402  read_fn = fd_read_from_mmap;
1403  seek_fn = fd_seek_from_mmap;
1404  buffersize = BLI_lseek(file, 0, SEEK_END);
1405  }
1406  }
1407 
1408  BLI_lseek(file, 0, SEEK_SET);
1409 
1410  /* Gzip file. */
1411  errno = 0;
1412  if ((read_fn == NULL) &&
1413  /* Check header magic. */
1414  (header[0] == 0x1f && header[1] == 0x8b)) {
1415  gzfile = BLI_gzopen(filepath, "rb");
1416  if (gzfile == (gzFile)Z_NULL) {
1417  BKE_reportf(reports,
1418  RPT_WARNING,
1419  "Unable to open '%s': %s",
1420  filepath,
1421  errno ? strerror(errno) : TIP_("unknown error reading file"));
1422  return NULL;
1423  }
1424 
1425  /* 'seek_fn' is too slow for gzip, don't set it. */
1426  read_fn = fd_read_gzip_from_file;
1427  /* Caller must close. */
1428  file = -1;
1429  }
1430 
1431  if (read_fn == NULL) {
1432  BKE_reportf(reports, RPT_WARNING, "Unrecognized file format '%s'", filepath);
1433  return NULL;
1434  }
1435 
1436  FileData *fd = filedata_new();
1437 
1438  fd->filedes = file;
1439  fd->gzfiledes = gzfile;
1440 
1441  fd->read = read_fn;
1442  fd->seek = seek_fn;
1443  fd->mmap_file = mmap_file;
1444  fd->buffersize = buffersize;
1445 
1446  return fd;
1447 }
1448 
1449 static FileData *blo_filedata_from_file_open(const char *filepath, ReportList *reports)
1450 {
1451  errno = 0;
1452  const int file = BLI_open(filepath, O_BINARY | O_RDONLY, 0);
1453  if (file == -1) {
1454  BKE_reportf(reports,
1455  RPT_WARNING,
1456  "Unable to open '%s': %s",
1457  filepath,
1458  errno ? strerror(errno) : TIP_("unknown error reading file"));
1459  return NULL;
1460  }
1461  FileData *fd = blo_filedata_from_file_descriptor(filepath, reports, file);
1462  if ((fd == NULL) || (fd->filedes == -1)) {
1463  close(file);
1464  }
1465  return fd;
1466 }
1467 
1468 /* cannot be called with relative paths anymore! */
1469 /* on each new library added, it now checks for the current FileData and expands relativeness */
1470 FileData *blo_filedata_from_file(const char *filepath, ReportList *reports)
1471 {
1472  FileData *fd = blo_filedata_from_file_open(filepath, reports);
1473  if (fd != NULL) {
1474  /* needed for library_append and read_libraries */
1475  BLI_strncpy(fd->relabase, filepath, sizeof(fd->relabase));
1476 
1477  return blo_decode_and_check(fd, reports);
1478  }
1479  return NULL;
1480 }
1481 
1486 static FileData *blo_filedata_from_file_minimal(const char *filepath)
1487 {
1488  FileData *fd = blo_filedata_from_file_open(filepath, NULL);
1489  if (fd != NULL) {
1491  if (fd->flags & FD_FLAGS_FILE_OK) {
1492  return fd;
1493  }
1494  blo_filedata_free(fd);
1495  }
1496  return NULL;
1497 }
1498 
1500  void *buffer,
1501  size_t size,
1502  bool *UNUSED(r_is_memchunck_identical))
1503 {
1504  int err;
1505 
1506  filedata->strm.next_out = (Bytef *)buffer;
1507  filedata->strm.avail_out = (uint)size;
1508 
1509  /* Inflate another chunk. */
1510  err = inflate(&filedata->strm, Z_SYNC_FLUSH);
1511 
1512  if (err == Z_STREAM_END) {
1513  return 0;
1514  }
1515  if (err != Z_OK) {
1516  printf("fd_read_gzip_from_memory: zlib error\n");
1517  return 0;
1518  }
1519 
1520  filedata->file_offset += size;
1521 
1522  return (ssize_t)size;
1523 }
1524 
1526 {
1527 
1528  fd->strm.next_in = (Bytef *)fd->buffer;
1529  fd->strm.avail_in = fd->buffersize;
1530  fd->strm.total_out = 0;
1531  fd->strm.zalloc = Z_NULL;
1532  fd->strm.zfree = Z_NULL;
1533 
1534  if (inflateInit2(&fd->strm, (16 + MAX_WBITS)) != Z_OK) {
1535  return 0;
1536  }
1537 
1539 
1540  return 1;
1541 }
1542 
1543 FileData *blo_filedata_from_memory(const void *mem, int memsize, ReportList *reports)
1544 {
1545  if (!mem || memsize < SIZEOFBLENDERHEADER) {
1546  BKE_report(reports, RPT_WARNING, (mem) ? TIP_("Unable to read") : TIP_("Unable to open"));
1547  return NULL;
1548  }
1549 
1550  FileData *fd = filedata_new();
1551  const char *cp = mem;
1552 
1553  fd->buffer = mem;
1554  fd->buffersize = memsize;
1555 
1556  /* test if gzip */
1557  if (cp[0] == 0x1f && cp[1] == 0x8b) {
1558  if (0 == fd_read_gzip_from_memory_init(fd)) {
1559  blo_filedata_free(fd);
1560  return NULL;
1561  }
1562  }
1563  else {
1564  fd->read = fd_read_from_memory;
1565  }
1566 
1568 
1569  return blo_decode_and_check(fd, reports);
1570 }
1571 
1573  const struct BlendFileReadParams *params,
1574  ReportList *reports)
1575 {
1576  if (!memfile) {
1577  BKE_report(reports, RPT_WARNING, "Unable to open blend <memory>");
1578  return NULL;
1579  }
1580 
1581  FileData *fd = filedata_new();
1582  fd->memfile = memfile;
1583  fd->undo_direction = params->undo_direction;
1584 
1585  fd->read = fd_read_from_memfile;
1587 
1588  return blo_decode_and_check(fd, reports);
1589 }
1590 
1592 {
1593  if (fd) {
1594  if (fd->filedes != -1) {
1595  close(fd->filedes);
1596  }
1597 
1598  if (fd->gzfiledes != NULL) {
1599  gzclose(fd->gzfiledes);
1600  }
1601 
1602  if (fd->strm.next_in) {
1603  if (inflateEnd(&fd->strm) != Z_OK) {
1604  printf("close gzip stream error\n");
1605  }
1606  }
1607 
1608  if (fd->buffer && !(fd->flags & FD_FLAGS_NOT_MY_BUFFER)) {
1609  MEM_freeN((void *)fd->buffer);
1610  fd->buffer = NULL;
1611  }
1612 
1613  if (fd->mmap_file) {
1614  BLI_mmap_free(fd->mmap_file);
1615  fd->mmap_file = NULL;
1616  }
1617 
1618  /* Free all BHeadN data blocks */
1619 #ifndef NDEBUG
1620  BLI_freelistN(&fd->bhead_list);
1621 #else
1622  /* Sanity check we're not keeping memory we don't need. */
1623  LISTBASE_FOREACH_MUTABLE (BHeadN *, new_bhead, &fd->bhead_list) {
1624  if (fd->seek != NULL && BHEAD_USE_READ_ON_DEMAND(&new_bhead->bhead)) {
1625  BLI_assert(new_bhead->has_data == 0);
1626  }
1627  MEM_freeN(new_bhead);
1628  }
1629 #endif
1630 
1631  if (fd->filesdna) {
1632  DNA_sdna_free(fd->filesdna);
1633  }
1634  if (fd->compflags) {
1635  MEM_freeN((void *)fd->compflags);
1636  }
1637  if (fd->reconstruct_info) {
1639  }
1640 
1641  if (fd->datamap) {
1642  oldnewmap_free(fd->datamap);
1643  }
1644  if (fd->globmap) {
1645  oldnewmap_free(fd->globmap);
1646  }
1647  if (fd->packedmap) {
1649  }
1650  if (fd->libmap && !(fd->flags & FD_FLAGS_NOT_MY_LIBMAP)) {
1651  oldnewmap_free(fd->libmap);
1652  }
1653  if (fd->old_idmap != NULL) {
1655  }
1657  if (fd->bheadmap) {
1658  MEM_freeN(fd->bheadmap);
1659  }
1660 
1661 #ifdef USE_GHASH_BHEAD
1662  if (fd->bhead_idname_hash) {
1664  }
1665 #endif
1666 
1667  MEM_freeN(fd);
1668  }
1669 }
1670 
1673 /* -------------------------------------------------------------------- */
1684 bool BLO_has_bfile_extension(const char *str)
1685 {
1686  const char *ext_test[4] = {".blend", ".ble", ".blend.gz", NULL};
1687  return BLI_path_extension_check_array(str, ext_test);
1688 }
1689 
1701 bool BLO_library_path_explode(const char *path, char *r_dir, char **r_group, char **r_name)
1702 {
1703  /* We might get some data names with slashes,
1704  * so we have to go up in path until we find blend file itself,
1705  * then we know next path item is group, and everything else is data name. */
1706  char *slash = NULL, *prev_slash = NULL, c = '\0';
1707 
1708  r_dir[0] = '\0';
1709  if (r_group) {
1710  *r_group = NULL;
1711  }
1712  if (r_name) {
1713  *r_name = NULL;
1714  }
1715 
1716  /* if path leads to an existing directory, we can be sure we're not (in) a library */
1717  if (BLI_is_dir(path)) {
1718  return false;
1719  }
1720 
1721  strcpy(r_dir, path);
1722 
1723  while ((slash = (char *)BLI_path_slash_rfind(r_dir))) {
1724  char tc = *slash;
1725  *slash = '\0';
1726  if (BLO_has_bfile_extension(r_dir) && BLI_is_file(r_dir)) {
1727  break;
1728  }
1729  if (STREQ(r_dir, BLO_EMBEDDED_STARTUP_BLEND)) {
1730  break;
1731  }
1732 
1733  if (prev_slash) {
1734  *prev_slash = c;
1735  }
1736  prev_slash = slash;
1737  c = tc;
1738  }
1739 
1740  if (!slash) {
1741  return false;
1742  }
1743 
1744  if (slash[1] != '\0') {
1745  BLI_assert(strlen(slash + 1) < BLO_GROUP_MAX);
1746  if (r_group) {
1747  *r_group = slash + 1;
1748  }
1749  }
1750 
1751  if (prev_slash && (prev_slash[1] != '\0')) {
1752  BLI_assert(strlen(prev_slash + 1) < MAX_ID_NAME - 2);
1753  if (r_name) {
1754  *r_name = prev_slash + 1;
1755  }
1756  }
1757 
1758  return true;
1759 }
1760 
1770 {
1771  FileData *fd;
1773  int *fd_data;
1774 
1775  fd = blo_filedata_from_file_minimal(filepath);
1776  fd_data = fd ? read_file_thumbnail(fd) : NULL;
1777 
1778  if (fd_data) {
1779  const int width = fd_data[0];
1780  const int height = fd_data[1];
1782  const size_t sz = BLEN_THUMB_MEMSIZE(width, height);
1783  data = MEM_mallocN(sz, __func__);
1784  if (data) {
1785  BLI_assert((sz - sizeof(*data)) ==
1786  (BLEN_THUMB_MEMSIZE_FILE(width, height) - (sizeof(*fd_data) * 2)));
1787  data->width = width;
1788  data->height = height;
1789  memcpy(data->rect, &fd_data[2], sz - sizeof(*data));
1790  }
1791  }
1792  }
1793 
1794  blo_filedata_free(fd);
1795 
1796  return data;
1797 }
1798 
1801 /* -------------------------------------------------------------------- */
1805 /* Only direct data-blocks. */
1806 static void *newdataadr(FileData *fd, const void *adr)
1807 {
1808  return oldnewmap_lookup_and_inc(fd->datamap, adr, true);
1809 }
1810 
1811 /* Only direct data-blocks. */
1812 static void *newdataadr_no_us(FileData *fd, const void *adr)
1813 {
1814  return oldnewmap_lookup_and_inc(fd->datamap, adr, false);
1815 }
1816 
1817 /* Direct datablocks with global linking. */
1819 {
1820  return oldnewmap_lookup_and_inc(fd->globmap, adr, true);
1821 }
1822 
1823 /* Used to restore packed data after undo. */
1824 static void *newpackedadr(FileData *fd, const void *adr)
1825 {
1826  if (fd->packedmap && adr) {
1827  return oldnewmap_lookup_and_inc(fd->packedmap, adr, true);
1828  }
1829 
1830  return oldnewmap_lookup_and_inc(fd->datamap, adr, true);
1831 }
1832 
1833 /* only lib data */
1834 static void *newlibadr(FileData *fd, const void *lib, const void *adr)
1835 {
1836  return oldnewmap_liblookup(fd->libmap, adr, lib);
1837 }
1838 
1839 /* only lib data */
1840 void *blo_do_versions_newlibadr(FileData *fd, const void *lib, const void *adr)
1841 {
1842  return newlibadr(fd, lib, adr);
1843 }
1844 
1845 /* increases user number */
1846 static void change_link_placeholder_to_real_ID_pointer_fd(FileData *fd, const void *old, void *new)
1847 {
1848  for (int i = 0; i < fd->libmap->nentries; i++) {
1849  OldNew *entry = &fd->libmap->entries[i];
1850 
1851  if (old == entry->newp && entry->nr == ID_LINK_PLACEHOLDER) {
1852  entry->newp = new;
1853  if (new) {
1854  entry->nr = GS(((ID *)new)->name);
1855  }
1856  }
1857  }
1858 }
1859 
1861  FileData *basefd,
1862  void *old,
1863  void *new)
1864 {
1865  LISTBASE_FOREACH (Main *, mainptr, mainlist) {
1866  FileData *fd;
1867 
1868  if (mainptr->curlib) {
1869  fd = mainptr->curlib->filedata;
1870  }
1871  else {
1872  fd = basefd;
1873  }
1874 
1875  if (fd) {
1877  }
1878  }
1879 }
1880 
1881 /* lib linked proxy objects point to our local data, we need
1882  * to clear that pointer before reading the undo memfile since
1883  * the object might be removed, it is set again in reading
1884  * if the local object still exists.
1885  * This is only valid for local proxy objects though, linked ones should not be affected here.
1886  */
1888 {
1889  LISTBASE_FOREACH (Object *, ob, &oldmain->objects) {
1890  if (ob->id.lib != NULL && ob->proxy_from != NULL && ob->proxy_from->id.lib == NULL) {
1891  ob->proxy_from = NULL;
1892  }
1893  }
1894 }
1895 
1896 /* XXX disabled this feature - packed files also belong in temp saves and quit.blend,
1897  * to make restore work. */
1898 
1900 {
1901  oldnewmap_insert(fd->packedmap, pf, pf, 0);
1902  oldnewmap_insert(fd->packedmap, pf->data, pf->data, 0);
1903 }
1904 
1906 {
1907  fd->packedmap = oldnewmap_new();
1908 
1909  LISTBASE_FOREACH (Image *, ima, &oldmain->images) {
1910  if (ima->packedfile) {
1911  insert_packedmap(fd, ima->packedfile);
1912  }
1913 
1914  LISTBASE_FOREACH (ImagePackedFile *, imapf, &ima->packedfiles) {
1915  if (imapf->packedfile) {
1916  insert_packedmap(fd, imapf->packedfile);
1917  }
1918  }
1919  }
1920 
1921  LISTBASE_FOREACH (VFont *, vfont, &oldmain->fonts) {
1922  if (vfont->packedfile) {
1923  insert_packedmap(fd, vfont->packedfile);
1924  }
1925  }
1926 
1927  LISTBASE_FOREACH (bSound *, sound, &oldmain->sounds) {
1928  if (sound->packedfile) {
1929  insert_packedmap(fd, sound->packedfile);
1930  }
1931  }
1932 
1933  LISTBASE_FOREACH (Volume *, volume, &oldmain->volumes) {
1934  if (volume->packedfile) {
1935  insert_packedmap(fd, volume->packedfile);
1936  }
1937  }
1938 
1939  LISTBASE_FOREACH (Library *, lib, &oldmain->libraries) {
1940  if (lib->packedfile) {
1941  insert_packedmap(fd, lib->packedfile);
1942  }
1943  }
1944 }
1945 
1946 /* set old main packed data to zero if it has been restored */
1947 /* this works because freeing old main only happens after this call */
1949 {
1950  OldNew *entry = fd->packedmap->entries;
1951 
1952  /* used entries were restored, so we put them to zero */
1953  for (int i = 0; i < fd->packedmap->nentries; i++, entry++) {
1954  if (entry->nr > 0) {
1955  entry->newp = NULL;
1956  }
1957  }
1958 
1959  LISTBASE_FOREACH (Image *, ima, &oldmain->images) {
1960  ima->packedfile = newpackedadr(fd, ima->packedfile);
1961 
1962  LISTBASE_FOREACH (ImagePackedFile *, imapf, &ima->packedfiles) {
1963  imapf->packedfile = newpackedadr(fd, imapf->packedfile);
1964  }
1965  }
1966 
1967  LISTBASE_FOREACH (VFont *, vfont, &oldmain->fonts) {
1968  vfont->packedfile = newpackedadr(fd, vfont->packedfile);
1969  }
1970 
1971  LISTBASE_FOREACH (bSound *, sound, &oldmain->sounds) {
1972  sound->packedfile = newpackedadr(fd, sound->packedfile);
1973  }
1974 
1975  LISTBASE_FOREACH (Library *, lib, &oldmain->libraries) {
1976  lib->packedfile = newpackedadr(fd, lib->packedfile);
1977  }
1978 
1979  LISTBASE_FOREACH (Volume *, volume, &oldmain->volumes) {
1980  volume->packedfile = newpackedadr(fd, volume->packedfile);
1981  }
1982 }
1983 
1984 /* undo file support: add all library pointers in lookup */
1986 {
1987  ListBase *lbarray[INDEX_ID_MAX];
1988 
1989  LISTBASE_FOREACH (Main *, ptr, old_mainlist) {
1990  int i = set_listbasepointers(ptr, lbarray);
1991  while (i--) {
1992  LISTBASE_FOREACH (ID *, id, lbarray[i]) {
1993  oldnewmap_insert(fd->libmap, id, id, GS(id->name));
1994  }
1995  }
1996  }
1997 
1998  fd->old_mainlist = old_mainlist;
1999 }
2000 
2001 /* Build a GSet of old main (we only care about local data here, so we can do that after
2002  * split_main() call. */
2004 {
2005  if (fd->old_idmap != NULL) {
2007  }
2009 }
2010 
2011 typedef struct BLOCacheStorage {
2015 
2018  const IDCacheKey *key,
2019  void **UNUSED(cache_p),
2020  uint UNUSED(flags),
2021  void *cache_storage_v)
2022 {
2024  UNUSED_VARS_NDEBUG(id);
2025 
2026  BLOCacheStorage *cache_storage = cache_storage_v;
2027  BLI_assert(!BLI_ghash_haskey(cache_storage->cache_map, key));
2028 
2029  IDCacheKey *storage_key = BLI_memarena_alloc(cache_storage->memarena, sizeof(*storage_key));
2030  *storage_key = *key;
2031  BLI_ghash_insert(cache_storage->cache_map, storage_key, POINTER_FROM_UINT(0));
2032 }
2033 
2036  ID *UNUSED(id), const IDCacheKey *key, void **cache_p, uint flags, void *cache_storage_v)
2037 {
2038  BLOCacheStorage *cache_storage = cache_storage_v;
2039 
2040  if (cache_storage == NULL) {
2041  /* In non-undo case, only clear the pointer if it is a purely runtime one.
2042  * If it may be stored in a persistent way in the .blend file, direct_link code is responsible
2043  * to properly deal with it. */
2044  if ((flags & IDTYPE_CACHE_CB_FLAGS_PERSISTENT) == 0) {
2045  *cache_p = NULL;
2046  }
2047  return;
2048  }
2049 
2050  void **value = BLI_ghash_lookup_p(cache_storage->cache_map, key);
2051  if (value == NULL) {
2052  *cache_p = NULL;
2053  return;
2054  }
2055  *value = POINTER_FROM_UINT(POINTER_AS_UINT(*value) + 1);
2056  *cache_p = key->cache_v;
2057 }
2058 
2061  const IDCacheKey *key,
2062  void **cache_p,
2063  uint UNUSED(flags),
2064  void *cache_storage_v)
2065 {
2066  BLOCacheStorage *cache_storage = cache_storage_v;
2067 
2068  void **value = BLI_ghash_lookup_p(cache_storage->cache_map, key);
2069  if (value == NULL) {
2070  *cache_p = NULL;
2071  return;
2072  }
2073  /* If that cache has been restored into some new ID, we want to remove it from old one, otherwise
2074  * keep it there so that it gets properly freed together with its ID. */
2075  *cache_p = POINTER_AS_UINT(*value) != 0 ? NULL : key->cache_v;
2076 }
2077 
2079 {
2080  if (fd->memfile != NULL) {
2081  BLI_assert(fd->cache_storage == NULL);
2082  fd->cache_storage = MEM_mallocN(sizeof(*fd->cache_storage), __func__);
2086 
2087  ListBase *lb;
2088  FOREACH_MAIN_LISTBASE_BEGIN (bmain, lb) {
2089  ID *id = lb->first;
2090  if (id == NULL) {
2091  continue;
2092  }
2093 
2094  const IDTypeInfo *type_info = BKE_idtype_get_info_from_id(id);
2095  if (type_info->foreach_cache == NULL) {
2096  continue;
2097  }
2098 
2100  if (ID_IS_LINKED(id)) {
2101  continue;
2102  }
2104  }
2106  }
2108  }
2109  else {
2110  fd->cache_storage = NULL;
2111  }
2112 }
2113 
2115 {
2116  if (fd->cache_storage != NULL) {
2117  ListBase *lb;
2118  FOREACH_MAIN_LISTBASE_BEGIN (bmain_old, lb) {
2119  ID *id = lb->first;
2120  if (id == NULL) {
2121  continue;
2122  }
2123 
2124  const IDTypeInfo *type_info = BKE_idtype_get_info_from_id(id);
2125  if (type_info->foreach_cache == NULL) {
2126  continue;
2127  }
2128 
2130  if (ID_IS_LINKED(id)) {
2131  continue;
2132  }
2134  }
2136  }
2138  }
2139 }
2140 
2142 {
2143  if (fd->cache_storage != NULL) {
2146  MEM_freeN(fd->cache_storage);
2147  fd->cache_storage = NULL;
2148  }
2149 }
2150 
2153 /* -------------------------------------------------------------------- */
2157 static void switch_endian_structs(const struct SDNA *filesdna, BHead *bhead)
2158 {
2159  int blocksize, nblocks;
2160  char *data;
2161 
2162  data = (char *)(bhead + 1);
2163  blocksize = filesdna->types_size[filesdna->structs[bhead->SDNAnr]->type];
2164 
2165  nblocks = bhead->nr;
2166  while (nblocks--) {
2167  DNA_struct_switch_endian(filesdna, bhead->SDNAnr, data);
2168 
2169  data += blocksize;
2170  }
2171 }
2172 
2173 static void *read_struct(FileData *fd, BHead *bh, const char *blockname)
2174 {
2175  void *temp = NULL;
2176 
2177  if (bh->len) {
2178 #ifdef USE_BHEAD_READ_ON_DEMAND
2179  BHead *bh_orig = bh;
2180 #endif
2181 
2182  /* switch is based on file dna */
2183  if (bh->SDNAnr && (fd->flags & FD_FLAGS_SWITCH_ENDIAN)) {
2184 #ifdef USE_BHEAD_READ_ON_DEMAND
2185  if (BHEADN_FROM_BHEAD(bh)->has_data == false) {
2186  bh = blo_bhead_read_full(fd, bh);
2187  if (UNLIKELY(bh == NULL)) {
2188  fd->flags &= ~FD_FLAGS_FILE_OK;
2189  return NULL;
2190  }
2191  }
2192 #endif
2194  }
2195 
2196  if (fd->compflags[bh->SDNAnr] != SDNA_CMP_REMOVED) {
2197  if (fd->compflags[bh->SDNAnr] == SDNA_CMP_NOT_EQUAL) {
2198 #ifdef USE_BHEAD_READ_ON_DEMAND
2199  if (BHEADN_FROM_BHEAD(bh)->has_data == false) {
2200  bh = blo_bhead_read_full(fd, bh);
2201  if (UNLIKELY(bh == NULL)) {
2202  fd->flags &= ~FD_FLAGS_FILE_OK;
2203  return NULL;
2204  }
2205  }
2206 #endif
2207  temp = DNA_struct_reconstruct(fd->reconstruct_info, bh->SDNAnr, bh->nr, (bh + 1));
2208  }
2209  else {
2210  /* SDNA_CMP_EQUAL */
2211  temp = MEM_mallocN(bh->len, blockname);
2212 #ifdef USE_BHEAD_READ_ON_DEMAND
2213  if (BHEADN_FROM_BHEAD(bh)->has_data) {
2214  memcpy(temp, (bh + 1), bh->len);
2215  }
2216  else {
2217  /* Instead of allocating the bhead, then copying it,
2218  * read the data from the file directly into the memory. */
2219  if (UNLIKELY(!blo_bhead_read_data(fd, bh, temp))) {
2220  fd->flags &= ~FD_FLAGS_FILE_OK;
2221  MEM_freeN(temp);
2222  temp = NULL;
2223  }
2224  }
2225 #else
2226  memcpy(temp, (bh + 1), bh->len);
2227 #endif
2228  }
2229  }
2230 
2231 #ifdef USE_BHEAD_READ_ON_DEMAND
2232  if (bh_orig != bh) {
2234  }
2235 #endif
2236  }
2237 
2238  return temp;
2239 }
2240 
2241 /* Like read_struct, but gets a pointer without allocating. Only works for
2242  * undo since DNA must match. */
2243 static const void *peek_struct_undo(FileData *fd, BHead *bhead)
2244 {
2245  BLI_assert(fd->memfile != NULL);
2246  UNUSED_VARS_NDEBUG(fd);
2247  return (bhead->len) ? (const void *)(bhead + 1) : NULL;
2248 }
2249 
2250 static void link_glob_list(FileData *fd, ListBase *lb) /* for glob data */
2251 {
2252  Link *ln, *prev;
2253  void *poin;
2254 
2255  if (BLI_listbase_is_empty(lb)) {
2256  return;
2257  }
2258  poin = newdataadr(fd, lb->first);
2259  if (lb->first) {
2260  oldnewmap_insert(fd->globmap, lb->first, poin, 0);
2261  }
2262  lb->first = poin;
2263 
2264  ln = lb->first;
2265  prev = NULL;
2266  while (ln) {
2267  poin = newdataadr(fd, ln->next);
2268  if (ln->next) {
2269  oldnewmap_insert(fd->globmap, ln->next, poin, 0);
2270  }
2271  ln->next = poin;
2272  ln->prev = prev;
2273  prev = ln;
2274  ln = ln->next;
2275  }
2276  lb->last = prev;
2277 }
2278 
2281 /* -------------------------------------------------------------------- */
2285 static void lib_link_id(BlendLibReader *reader, ID *id);
2286 
2287 static void lib_link_id_embedded_id(BlendLibReader *reader, ID *id)
2288 {
2289 
2290  /* Handle 'private IDs'. */
2291  bNodeTree *nodetree = ntreeFromID(id);
2292  if (nodetree != NULL) {
2293  lib_link_id(reader, &nodetree->id);
2294  ntreeBlendReadLib(reader, nodetree);
2295  }
2296 
2297  if (GS(id->name) == ID_SCE) {
2298  Scene *scene = (Scene *)id;
2299  if (scene->master_collection != NULL) {
2300  lib_link_id(reader, &scene->master_collection->id);
2302  }
2303  }
2304 }
2305 
2306 static void lib_link_id(BlendLibReader *reader, ID *id)
2307 {
2308  /* Note: WM IDProperties are never written to file, hence they should always be NULL here. */
2309  BLI_assert((GS(id->name) != ID_WM) || id->properties == NULL);
2310  IDP_BlendReadLib(reader, id->properties);
2311 
2312  AnimData *adt = BKE_animdata_from_id(id);
2313  if (adt != NULL) {
2314  BKE_animdata_blend_read_lib(reader, id, adt);
2315  }
2316 
2317  if (id->override_library) {
2320  }
2321 
2322  lib_link_id_embedded_id(reader, id);
2323 }
2324 
2326 {
2328 
2330  BLO_read_data_address(reader, &opop->subitem_local_name);
2331 
2332  opop->tag = 0; /* Runtime only. */
2333 }
2334 
2336 {
2338 
2339  BLO_read_data_address(reader, &op->rna_path);
2340 
2341  op->tag = 0; /* Runtime only. */
2342 
2344 }
2345 
2346 static void direct_link_id_common(
2347  BlendDataReader *reader, Library *current_library, ID *id, ID *id_old, const int tag);
2348 
2350  Library *current_library,
2351  ID *id,
2352  ID *id_old)
2353 {
2354  /* Handle 'private IDs'. */
2355  bNodeTree **nodetree = BKE_ntree_ptr_from_id(id);
2356  if (nodetree != NULL && *nodetree != NULL) {
2357  BLO_read_data_address(reader, nodetree);
2358  direct_link_id_common(reader,
2359  current_library,
2360  (ID *)*nodetree,
2361  id_old != NULL ? (ID *)ntreeFromID(id_old) : NULL,
2362  0);
2363  ntreeBlendReadData(reader, *nodetree);
2364  }
2365 
2366  if (GS(id->name) == ID_SCE) {
2367  Scene *scene = (Scene *)id;
2368  if (scene->master_collection != NULL) {
2370  direct_link_id_common(reader,
2371  current_library,
2373  id_old != NULL ? &((Scene *)id_old)->master_collection->id : NULL,
2374  0);
2376  }
2377  }
2378 }
2379 
2380 static int direct_link_id_restore_recalc_exceptions(const ID *id_current)
2381 {
2382  /* Exception for armature objects, where the pose has direct points to the
2383  * armature databolock. */
2384  if (GS(id_current->name) == ID_OB && ((Object *)id_current)->pose) {
2385  return ID_RECALC_GEOMETRY;
2386  }
2387 
2388  return 0;
2389 }
2390 
2392  const ID *id_target,
2393  const ID *id_current,
2394  const bool is_identical)
2395 {
2396  /* These are the evaluations that had not been performed yet at the time the
2397  * target undo state was written. These need to be done again, since they may
2398  * flush back changes to the original datablock. */
2399  int recalc = id_target->recalc;
2400 
2401  if (id_current == NULL) {
2402  /* ID does not currently exist in the database, so also will not exist in
2403  * the dependency graphs. That means it will be newly created and as a
2404  * result also fully re-evaluated regardless of the recalc flag set here. */
2405  recalc |= ID_RECALC_ALL;
2406  }
2407  else {
2408  /* If the contents datablock changed, the depsgraph needs to copy the
2409  * datablock again to ensure it matches the original datablock. */
2410  if (!is_identical) {
2411  recalc |= ID_RECALC_COPY_ON_WRITE;
2412  }
2413 
2414  /* Special exceptions. */
2415  recalc |= direct_link_id_restore_recalc_exceptions(id_current);
2416 
2417  /* Evaluations for the current state that have not been performed yet
2418  * by the time we are performing this undo step. */
2419  recalc |= id_current->recalc;
2420 
2421  /* Tags that were set between the target state and the current state,
2422  * that we need to perform again. */
2423  if (fd->undo_direction == STEP_UNDO) {
2424  /* Undo: tags from target to the current state. */
2425  recalc |= id_current->recalc_up_to_undo_push;
2426  }
2427  else {
2429  /* Redo: tags from current to the target state. */
2430  recalc |= id_target->recalc_up_to_undo_push;
2431  }
2432  }
2433 
2434  return recalc;
2435 }
2436 
2438  BlendDataReader *reader, Library *current_library, ID *id, ID *id_old, const int tag)
2439 {
2440  if (!BLO_read_data_is_undo(reader)) {
2441  /* When actually reading a file , we do want to reset/re-generate session uuids.
2442  * In undo case, we want to re-use existing ones. */
2443  id->session_uuid = MAIN_ID_SESSION_UUID_UNSET;
2444  }
2445 
2446  if ((tag & LIB_TAG_TEMP_MAIN) == 0) {
2448  }
2449 
2450  id->lib = current_library;
2451  id->us = ID_FAKE_USERS(id);
2452  id->icon_id = 0;
2453  id->newid = NULL; /* Needed because .blend may have been saved with crap value here... */
2454  id->orig_id = NULL;
2455  id->py_instance = NULL;
2456 
2457  /* Initialize with provided tag. */
2458  id->tag = tag;
2459 
2460  if (tag & LIB_TAG_ID_LINK_PLACEHOLDER) {
2461  /* For placeholder we only need to set the tag and properly initialize generic ID fields above,
2462  * no further data to read. */
2463  return;
2464  }
2465 
2466  if (id->asset_data) {
2467  BLO_read_data_address(reader, &id->asset_data);
2469  }
2470 
2471  /*link direct data of ID properties*/
2472  if (id->properties) {
2473  BLO_read_data_address(reader, &id->properties);
2474  /* this case means the data was written incorrectly, it should not happen */
2475  IDP_BlendDataRead(reader, &id->properties);
2476  }
2477 
2478  id->flag &= ~LIB_INDIRECT_WEAK_LINK;
2479 
2480  /* NOTE: It is important to not clear the recalc flags for undo/redo.
2481  * Preserving recalc flags on redo/undo is the only way to make dependency graph detect
2482  * that animation is to be evaluated on undo/redo. If this is not enforced by the recalc
2483  * flags dependency graph does not do animation update to avoid loss of unkeyed changes.,
2484  * which conflicts with undo/redo of changes to animation data itself.
2485  *
2486  * But for regular file load we clear the flag, since the flags might have been changed since
2487  * the version the file has been saved with. */
2488  if (!BLO_read_data_is_undo(reader)) {
2489  id->recalc = 0;
2490  id->recalc_after_undo_push = 0;
2491  }
2492  else if ((reader->fd->skip_flags & BLO_READ_SKIP_UNDO_OLD_MAIN) == 0) {
2493  id->recalc = direct_link_id_restore_recalc(reader->fd, id, id_old, false);
2494  id->recalc_after_undo_push = 0;
2495  }
2496 
2497  /* Link direct data of overrides. */
2498  if (id->override_library) {
2500  /* Work around file corruption on writing, see T86853. */
2501  if (id->override_library != NULL) {
2504  id->override_library->runtime = NULL;
2505  }
2506  }
2507 
2508  DrawDataList *drawdata = DRW_drawdatalist_from_id(id);
2509  if (drawdata) {
2510  BLI_listbase_clear((ListBase *)drawdata);
2511  }
2512 
2513  /* Handle 'private IDs'. */
2514  direct_link_id_embedded_id(reader, current_library, id, id_old);
2515 }
2516 
2519 /* -------------------------------------------------------------------- */
2525 /* -------------------------------------------------------------------- */
2530 {
2531  key->uidgen = 1;
2532  LISTBASE_FOREACH (KeyBlock *, block, &key->block) {
2533  block->uid = key->uidgen++;
2534  }
2535 }
2536 
2539 /* -------------------------------------------------------------------- */
2543 #ifdef USE_SETSCENE_CHECK
2547 static bool scene_validate_setscene__liblink(Scene *sce, const int totscene)
2548 {
2549  Scene *sce_iter;
2550  int a;
2551 
2552  if (sce->set == NULL) {
2553  return true;
2554  }
2555 
2556  for (a = 0, sce_iter = sce; sce_iter->set; sce_iter = sce_iter->set, a++) {
2557  /* This runs per library (before each libraries #Main has been joined),
2558  * so we can't step into other libraries since `totscene` is only for this library.
2559  *
2560  * Also, other libraries may not have been linked yet,
2561  * while we could check #LIB_TAG_NEED_LINK the library pointer check is sufficient. */
2562  if (sce->id.lib != sce_iter->id.lib) {
2563  return true;
2564  }
2566  return true;
2567  }
2568 
2569  if (a > totscene) {
2570  sce->set = NULL;
2571  return false;
2572  }
2573  }
2574 
2575  return true;
2576 }
2577 #endif
2578 
2579 static void lib_link_scenes_check_set(Main *bmain)
2580 {
2581 #ifdef USE_SETSCENE_CHECK
2582  const int totscene = BLI_listbase_count(&bmain->scenes);
2583  LISTBASE_FOREACH (Scene *, sce, &bmain->scenes) {
2586  if (!scene_validate_setscene__liblink(sce, totscene)) {
2587  printf("Found cyclic background scene when linking %s\n", sce->id.name + 2);
2588  }
2589  }
2590  }
2591 #else
2592  UNUSED_VARS(bmain, totscene);
2593 #endif
2594 }
2595 
2596 #undef USE_SETSCENE_CHECK
2597 
2600 /* -------------------------------------------------------------------- */
2604 /* how to handle user count on pointer restore */
2605 typedef enum ePointerUserMode {
2606  USER_IGNORE = 0, /* ignore user count */
2607  USER_REAL = 1, /* ensure at least one real user (fake user ignored) */
2609 
2610 static void restore_pointer_user(ID *id, ID *newid, ePointerUserMode user)
2611 {
2612  BLI_assert(STREQ(newid->name + 2, id->name + 2));
2613  BLI_assert(newid->lib == id->lib);
2614  UNUSED_VARS_NDEBUG(id);
2615 
2616  if (user == USER_REAL) {
2617  id_us_ensure_real(newid);
2618  }
2619 }
2620 
2621 #ifndef USE_GHASH_RESTORE_POINTER
2627 static void *restore_pointer_by_name_main(Main *mainp, ID *id, ePointerUserMode user)
2628 {
2629  if (id) {
2630  ListBase *lb = which_libbase(mainp, GS(id->name));
2631  if (lb) { /* there's still risk of checking corrupt mem (freed Ids in oops) */
2632  ID *idn = lb->first;
2633  for (; idn; idn = idn->next) {
2634  if (STREQ(idn->name + 2, id->name + 2)) {
2635  if (idn->lib == id->lib) {
2636  restore_pointer_user(id, idn, user);
2637  break;
2638  }
2639  }
2640  }
2641  return idn;
2642  }
2643  }
2644  return NULL;
2645 }
2646 #endif
2647 
2659 {
2660 #ifdef USE_GHASH_RESTORE_POINTER
2661  if (id) {
2662  /* use fast lookup when available */
2663  ID *idn = BKE_main_idmap_lookup_id(id_map, id);
2664  if (idn) {
2665  restore_pointer_user(id, idn, user);
2666  }
2667  return idn;
2668  }
2669  return NULL;
2670 #else
2672  return restore_pointer_by_name_main(mainp, id, user);
2673 #endif
2674 }
2675 
2677 {
2678  if (id) {
2679  /* clipboard must ensure this */
2680  BLI_assert(id->newid != NULL);
2682  }
2683 }
2684 static int lib_link_seq_clipboard_cb(Sequence *seq, void *arg_pt)
2685 {
2686  struct IDNameLib_Map *id_map = arg_pt;
2687 
2693  return 1;
2694 }
2695 
2697 {
2698  /* update IDs stored in sequencer clipboard */
2700 }
2701 
2703 {
2704  const int cb_flag = cb_data->cb_flag;
2705  ID **id_pointer = cb_data->id_pointer;
2706  if (cb_flag & IDWALK_CB_EMBEDDED || *id_pointer == NULL) {
2707  return IDWALK_RET_NOP;
2708  }
2709 
2710  /* Special ugly case here, thanks again for those non-IDs IDs... */
2711  /* We probably need to add more cases here (hint: nodetrees),
2712  * but will wait for changes from D5559 to get in first. */
2713  if (GS((*id_pointer)->name) == ID_GR) {
2714  Collection *collection = (Collection *)*id_pointer;
2715  if (collection->flag & COLLECTION_IS_MASTER) {
2716  /* We should never reach that point anymore, since master collection private ID should be
2717  * properly tagged with IDWALK_CB_EMBEDDED. */
2718  BLI_assert(0);
2719  return IDWALK_RET_NOP;
2720  }
2721  }
2722 
2723  struct IDNameLib_Map *id_map = cb_data->user_data;
2724 
2725  /* Note: Handling of usercount here is really bad, defining its own system...
2726  * Will have to be refactored at some point, but that is not top priority task for now.
2727  * And all user-counts are properly recomputed at the end of the undo management code anyway. */
2728  *id_pointer = restore_pointer_by_name(
2729  id_map, *id_pointer, (cb_flag & IDWALK_CB_USER_ONE) ? USER_REAL : USER_IGNORE);
2730 
2731  return IDWALK_RET_NOP;
2732 }
2733 
2734 static void lib_link_main_data_restore(struct IDNameLib_Map *id_map, Main *newmain)
2735 {
2736  ID *id;
2737  FOREACH_MAIN_ID_BEGIN (newmain, id) {
2739  }
2741 }
2742 
2744 {
2747 }
2748 
2750 {
2752 
2753  LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
2754  LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
2755  if (sl->spacetype == SPACE_VIEW3D) {
2756  View3D *v3d = (View3D *)sl;
2757 
2758  if (v3d->camera == NULL || v3d->scenelock) {
2759  v3d->camera = scene->camera;
2760  }
2761 
2762  if (v3d->localvd) {
2763  Base *base = NULL;
2764 
2765  v3d->localvd->camera = scene->camera;
2766 
2767  /* Local-view can become invalid during undo/redo steps,
2768  * so we exit it when no could be found. */
2769  for (base = view_layer->object_bases.first; base; base = base->next) {
2770  if (base->local_view_bits & v3d->local_view_uuid) {
2771  break;
2772  }
2773  }
2774  if (base == NULL) {
2775  MEM_freeN(v3d->localvd);
2776  v3d->localvd = NULL;
2777  v3d->local_view_uuid = 0;
2778 
2779  /* Region-base storage is different depending if the space is active. */
2780  ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase :
2781  &sl->regionbase;
2782  LISTBASE_FOREACH (ARegion *, region, regionbase) {
2783  if (region->regiontype == RGN_TYPE_WINDOW) {
2784  RegionView3D *rv3d = region->regiondata;
2785  if (rv3d->localvd) {
2786  MEM_freeN(rv3d->localvd);
2787  rv3d->localvd = NULL;
2788  }
2789  }
2790  }
2791  }
2792  }
2793  }
2794  }
2795  }
2796 }
2797 
2799  Main *newmain,
2800  WorkSpaceLayout *layout)
2801 {
2802  bScreen *screen = BKE_workspace_layout_screen_get(layout);
2803 
2804  /* avoid conflicts with 2.8x branch */
2805  {
2806  LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
2807  LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
2808  if (sl->spacetype == SPACE_VIEW3D) {
2809  View3D *v3d = (View3D *)sl;
2810 
2813  }
2814  else if (sl->spacetype == SPACE_GRAPH) {
2815  SpaceGraph *sipo = (SpaceGraph *)sl;
2816  bDopeSheet *ads = sipo->ads;
2817 
2818  if (ads) {
2820 
2821  if (ads->filter_grp) {
2823  id_map, (ID *)ads->filter_grp, USER_IGNORE);
2824  }
2825  }
2826 
2827  /* force recalc of list of channels (i.e. includes calculating F-Curve colors)
2828  * thus preventing the "black curves" problem post-undo
2829  */
2831  }
2832  else if (sl->spacetype == SPACE_PROPERTIES) {
2833  SpaceProperties *sbuts = (SpaceProperties *)sl;
2835  if (sbuts->pinid == NULL) {
2836  sbuts->flag &= ~SB_PIN_CONTEXT;
2837  }
2838 
2839  /* TODO: restore path pointers: T40046
2840  * (complicated because this contains data pointers too, not just ID)*/
2841  MEM_SAFE_FREE(sbuts->path);
2842  }
2843  else if (sl->spacetype == SPACE_FILE) {
2844  SpaceFile *sfile = (SpaceFile *)sl;
2845  sfile->op = NULL;
2846  sfile->previews_timer = NULL;
2848  }
2849  else if (sl->spacetype == SPACE_ACTION) {
2850  SpaceAction *saction = (SpaceAction *)sl;
2851 
2852  saction->action = restore_pointer_by_name(id_map, (ID *)saction->action, USER_REAL);
2853  saction->ads.source = restore_pointer_by_name(
2854  id_map, (ID *)saction->ads.source, USER_REAL);
2855 
2856  if (saction->ads.filter_grp) {
2858  id_map, (ID *)saction->ads.filter_grp, USER_IGNORE);
2859  }
2860 
2861  /* force recalc of list of channels, potentially updating the active action
2862  * while we're at it (as it can only be updated that way) T28962.
2863  */
2865  }
2866  else if (sl->spacetype == SPACE_IMAGE) {
2867  SpaceImage *sima = (SpaceImage *)sl;
2868 
2869  sima->image = restore_pointer_by_name(id_map, (ID *)sima->image, USER_REAL);
2870 
2871  /* this will be freed, not worth attempting to find same scene,
2872  * since it gets initialized later */
2873  sima->iuser.scene = NULL;
2874 
2875 #if 0
2876  /* Those are allocated and freed by space code, no need to handle them here. */
2880  MEM_SAFE_FREE(sima->scopes.vecscope);
2881 #endif
2882  sima->scopes.ok = 0;
2883 
2884  /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data
2885  * so assume that here we're doing for undo only...
2886  */
2887  sima->gpd = restore_pointer_by_name(id_map, (ID *)sima->gpd, USER_REAL);
2889  id_map, (ID *)sima->mask_info.mask, USER_REAL);
2890  }
2891  else if (sl->spacetype == SPACE_SEQ) {
2892  SpaceSeq *sseq = (SpaceSeq *)sl;
2893 
2894  /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data
2895  * so assume that here we're doing for undo only...
2896  */
2897  sseq->gpd = restore_pointer_by_name(id_map, (ID *)sseq->gpd, USER_REAL);
2898  }
2899  else if (sl->spacetype == SPACE_NLA) {
2900  SpaceNla *snla = (SpaceNla *)sl;
2901  bDopeSheet *ads = snla->ads;
2902 
2903  if (ads) {
2905 
2906  if (ads->filter_grp) {
2908  id_map, (ID *)ads->filter_grp, USER_IGNORE);
2909  }
2910  }
2911  }
2912  else if (sl->spacetype == SPACE_TEXT) {
2913  SpaceText *st = (SpaceText *)sl;
2914 
2916  if (st->text == NULL) {
2917  st->text = newmain->texts.first;
2918  }
2919  }
2920  else if (sl->spacetype == SPACE_SCRIPT) {
2921  SpaceScript *scpt = (SpaceScript *)sl;
2922 
2924 
2925  /*screen->script = NULL; - 2.45 set to null, better re-run the script */
2926  if (scpt->script) {
2927  SCRIPT_SET_NULL(scpt->script);
2928  }
2929  }
2930  else if (sl->spacetype == SPACE_OUTLINER) {
2931  SpaceOutliner *space_outliner = (SpaceOutliner *)sl;
2932 
2933  space_outliner->search_tse.id = restore_pointer_by_name(
2934  id_map, space_outliner->search_tse.id, USER_IGNORE);
2935 
2936  if (space_outliner->treestore) {
2937  TreeStoreElem *tselem;
2938  BLI_mempool_iter iter;
2939 
2940  BLI_mempool_iternew(space_outliner->treestore, &iter);
2941  while ((tselem = BLI_mempool_iterstep(&iter))) {
2942  /* Do not try to restore pointers to drivers/sequence/etc.,
2943  * can crash in undo case! */
2944  if (TSE_IS_REAL_ID(tselem)) {
2945  tselem->id = restore_pointer_by_name(id_map, tselem->id, USER_IGNORE);
2946  }
2947  else {
2948  tselem->id = NULL;
2949  }
2950  }
2951  /* rebuild hash table, because it depends on ids too */
2952  space_outliner->storeflag |= SO_TREESTORE_REBUILD;
2953  }
2954  }
2955  else if (sl->spacetype == SPACE_NODE) {
2956  SpaceNode *snode = (SpaceNode *)sl;
2957  bNodeTreePath *path, *path_next;
2958  bNodeTree *ntree;
2959 
2960  /* node tree can be stored locally in id too, link this first */
2961  snode->id = restore_pointer_by_name(id_map, snode->id, USER_REAL);
2962  snode->from = restore_pointer_by_name(id_map, snode->from, USER_IGNORE);
2963 
2964  ntree = snode->id ? ntreeFromID(snode->id) : NULL;
2965  snode->nodetree = ntree ?
2966  ntree :
2968 
2969  for (path = snode->treepath.first; path; path = path->next) {
2970  if (path == snode->treepath.first) {
2971  /* first nodetree in path is same as snode->nodetree */
2972  path->nodetree = snode->nodetree;
2973  }
2974  else {
2976  }
2977 
2978  if (!path->nodetree) {
2979  break;
2980  }
2981  }
2982 
2983  /* remaining path entries are invalid, remove */
2984  for (; path; path = path_next) {
2985  path_next = path->next;
2986 
2987  BLI_remlink(&snode->treepath, path);
2988  MEM_freeN(path);
2989  }
2990 
2991  /* edittree is just the last in the path,
2992  * set this directly since the path may have been shortened above */
2993  if (snode->treepath.last) {
2994  path = snode->treepath.last;
2995  snode->edittree = path->nodetree;
2996  }
2997  else {
2998  snode->edittree = NULL;
2999  }
3000  }
3001  else if (sl->spacetype == SPACE_CLIP) {
3002  SpaceClip *sclip = (SpaceClip *)sl;
3003 
3004  sclip->clip = restore_pointer_by_name(id_map, (ID *)sclip->clip, USER_REAL);
3006  id_map, (ID *)sclip->mask_info.mask, USER_REAL);
3007 
3008  sclip->scopes.ok = 0;
3009  }
3010  else if (sl->spacetype == SPACE_SPREADSHEET) {
3011  SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)sl;
3012 
3014  if (context->type == SPREADSHEET_CONTEXT_OBJECT) {
3016  object_context->object = restore_pointer_by_name(
3017  id_map, (ID *)object_context->object, USER_IGNORE);
3018  }
3019  }
3020  }
3021  }
3022  }
3023  }
3024 }
3025 
3031  Main *newmain,
3032  wmWindowManager *curwm,
3033  Scene *curscene,
3034  ViewLayer *cur_view_layer)
3035 {
3037  newmain, true, oldmain, MAIN_IDMAP_TYPE_NAME);
3038 
3039  LISTBASE_FOREACH (WorkSpace *, workspace, &newmain->workspaces) {
3040  LISTBASE_FOREACH (WorkSpaceLayout *, layout, &workspace->layouts) {
3041  lib_link_workspace_layout_restore(id_map, newmain, layout);
3042  }
3043  }
3044 
3045  LISTBASE_FOREACH (wmWindow *, win, &curwm->windows) {
3046  WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
3047  ID *workspace_id = (ID *)workspace;
3048  Scene *oldscene = win->scene;
3049 
3050  workspace = restore_pointer_by_name(id_map, workspace_id, USER_REAL);
3051  BKE_workspace_active_set(win->workspace_hook, workspace);
3052  win->scene = restore_pointer_by_name(id_map, (ID *)win->scene, USER_REAL);
3053  if (win->scene == NULL) {
3054  win->scene = curscene;
3055  }
3056  if (BKE_view_layer_find(win->scene, win->view_layer_name) == NULL) {
3057  STRNCPY(win->view_layer_name, cur_view_layer->name);
3058  }
3059  BKE_workspace_active_set(win->workspace_hook, workspace);
3060 
3061  /* keep cursor location through undo */
3062  memcpy(&win->scene->cursor, &oldscene->cursor, sizeof(win->scene->cursor));
3063 
3064  /* Note: even though that function seems to redo part of what is done by
3065  * `lib_link_workspace_layout_restore()` above, it seems to have a slightly different scope:
3066  * while the former updates the whole UI pointers from Main db (going over all layouts of
3067  * all workspaces), that one only focuses one current active screen, takes care of
3068  * potential local view, and needs window's scene pointer to be final... */
3069  lib_link_window_scene_data_restore(win, win->scene, cur_view_layer);
3070 
3071  BLI_assert(win->screen == NULL);
3072  }
3073 
3075 
3076  /* Restore all ID pointers in Main database itself
3077  * (especially IDProperties might point to some word-space of other 'weirdly unchanged' ID
3078  * pointers, see T69146).
3079  * Note that this will re-apply again a few pointers in workspaces or so,
3080  * but since we are remapping final ones already set above,
3081  * that is just some minor harmless double-processing. */
3083 
3084  /* update IDs stored in all possible clipboards */
3086 
3088 }
3089 
3092 /* -------------------------------------------------------------------- */
3097 {
3098  Main *newmain;
3099 
3100  /* check if the library was already read */
3101  for (newmain = fd->mainlist->first; newmain; newmain = newmain->next) {
3102  if (newmain->curlib) {
3103  if (BLI_path_cmp(newmain->curlib->filepath_abs, lib->filepath_abs) == 0) {
3105  RPT_WARNING,
3106  TIP_("Library '%s', '%s' had multiple instances, save and reload!"),
3107  lib->filepath,
3108  lib->filepath_abs);
3109 
3111  /* change_link_placeholder_to_real_ID_pointer_fd(fd, lib, newmain->curlib); */
3112 
3113  BLI_remlink(&main->libraries, lib);
3114  MEM_freeN(lib);
3115 
3116  /* Now, since Blender always expect **latest** Main pointer from fd->mainlist
3117  * to be the active library Main pointer,
3118  * where to add all non-library data-blocks found in file next, we have to switch that
3119  * 'dupli' found Main to latest position in the list!
3120  * Otherwise, you get weird disappearing linked data on a rather inconsistent basis.
3121  * See also T53977 for reproducible case. */
3122  BLI_remlink(fd->mainlist, newmain);
3123  BLI_addtail(fd->mainlist, newmain);
3124 
3125  return;
3126  }
3127  }
3128  }
3129 
3130  /* Make sure we have full path in lib->filepath_abs */
3131  BLI_strncpy(lib->filepath_abs, lib->filepath, sizeof(lib->filepath));
3132  BLI_path_normalize(fd->relabase, lib->filepath_abs);
3133 
3134  // printf("direct_link_library: filepath %s\n", lib->filepath);
3135  // printf("direct_link_library: filepath_abs %s\n", lib->filepath_abs);
3136 
3137  BlendDataReader reader = {fd};
3138  BKE_packedfile_blend_read(&reader, &lib->packedfile);
3139 
3140  /* new main */
3141  newmain = BKE_main_new();
3142  BLI_addtail(fd->mainlist, newmain);
3143  newmain->curlib = lib;
3144 
3145  lib->parent = NULL;
3146 
3147  id_us_ensure_real(&lib->id);
3148 }
3149 
3151 {
3152 }
3153 
3154 /* Always call this once you have loaded new library data to set the relative paths correctly
3155  * in relation to the blend file. */
3156 static void fix_relpaths_library(const char *basepath, Main *main)
3157 {
3158  /* BLO_read_from_memory uses a blank filename */
3159  if (basepath == NULL || basepath[0] == '\0') {
3160  LISTBASE_FOREACH (Library *, lib, &main->libraries) {
3161  /* when loading a linked lib into a file which has not been saved,
3162  * there is nothing we can be relative to, so instead we need to make
3163  * it absolute. This can happen when appending an object with a relative
3164  * link into an unsaved blend file. See T27405.
3165  * The remap relative option will make it relative again on save - campbell */
3166  if (BLI_path_is_rel(lib->filepath)) {
3167  BLI_strncpy(lib->filepath, lib->filepath_abs, sizeof(lib->filepath));
3168  }
3169  }
3170  }
3171  else {
3172  LISTBASE_FOREACH (Library *, lib, &main->libraries) {
3173  /* Libraries store both relative and abs paths, recreate relative paths,
3174  * relative to the blend file since indirectly linked libs will be
3175  * relative to their direct linked library. */
3176  if (BLI_path_is_rel(lib->filepath)) { /* if this is relative to begin with? */
3177  BLI_strncpy(lib->filepath, lib->filepath_abs, sizeof(lib->filepath));
3178  BLI_path_rel(lib->filepath, basepath);
3179  }
3180  }
3181  }
3182 }
3183 
3186 /* -------------------------------------------------------------------- */
3190 static ID *create_placeholder(Main *mainvar, const short idcode, const char *idname, const int tag)
3191 {
3192  ListBase *lb = which_libbase(mainvar, idcode);
3193  ID *ph_id = BKE_libblock_alloc_notest(idcode);
3194 
3195  *((short *)ph_id->name) = idcode;
3196  BLI_strncpy(ph_id->name + 2, idname, sizeof(ph_id->name) - 2);
3197  BKE_libblock_init_empty(ph_id);
3198  ph_id->lib = mainvar->curlib;
3199  ph_id->tag = tag | LIB_TAG_MISSING;
3200  ph_id->us = ID_FAKE_USERS(ph_id);
3201  ph_id->icon_id = 0;
3202 
3203  BLI_addtail(lb, ph_id);
3204  id_sort_by_name(lb, ph_id, NULL);
3205 
3206  if ((tag & LIB_TAG_TEMP_MAIN) == 0) {
3208  }
3209 
3210  return ph_id;
3211 }
3212 
3214 {
3215  /* Placeholder ObData IDs won't have any material, we have to update their objects for that,
3216  * otherwise the inconsistency between both will lead to crashes (especially in Eevee?). */
3217  LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
3218  ID *obdata = ob->data;
3219  if (obdata != NULL && obdata->tag & LIB_TAG_MISSING) {
3220  BKE_object_materials_test(bmain, ob, obdata);
3221  }
3222  }
3223 }
3224 
3225 static const char *dataname(short id_code)
3226 {
3227  switch ((ID_Type)id_code) {
3228  case ID_OB:
3229  return "Data from OB";
3230  case ID_ME:
3231  return "Data from ME";
3232  case ID_IP:
3233  return "Data from IP";
3234  case ID_SCE:
3235  return "Data from SCE";
3236  case ID_MA:
3237  return "Data from MA";
3238  case ID_TE:
3239  return "Data from TE";
3240  case ID_CU:
3241  return "Data from CU";
3242  case ID_GR:
3243  return "Data from GR";
3244  case ID_AR:
3245  return "Data from AR";
3246  case ID_AC:
3247  return "Data from AC";
3248  case ID_LI:
3249  return "Data from LI";
3250  case ID_MB:
3251  return "Data from MB";
3252  case ID_IM:
3253  return "Data from IM";
3254  case ID_LT:
3255  return "Data from LT";
3256  case ID_LA:
3257  return "Data from LA";
3258  case ID_CA:
3259  return "Data from CA";
3260  case ID_KE:
3261  return "Data from KE";
3262  case ID_WO:
3263  return "Data from WO";
3264  case ID_SCR:
3265  return "Data from SCR";
3266  case ID_VF:
3267  return "Data from VF";
3268  case ID_TXT:
3269  return "Data from TXT";
3270  case ID_SPK:
3271  return "Data from SPK";
3272  case ID_LP:
3273  return "Data from LP";
3274  case ID_SO:
3275  return "Data from SO";
3276  case ID_NT:
3277  return "Data from NT";
3278  case ID_BR:
3279  return "Data from BR";
3280  case ID_PA:
3281  return "Data from PA";
3282  case ID_PAL:
3283  return "Data from PAL";
3284  case ID_PC:
3285  return "Data from PCRV";
3286  case ID_GD:
3287  return "Data from GD";
3288  case ID_WM:
3289  return "Data from WM";
3290  case ID_MC:
3291  return "Data from MC";
3292  case ID_MSK:
3293  return "Data from MSK";
3294  case ID_LS:
3295  return "Data from LS";
3296  case ID_CF:
3297  return "Data from CF";
3298  case ID_WS:
3299  return "Data from WS";
3300  case ID_HA:
3301  return "Data from HA";
3302  case ID_PT:
3303  return "Data from PT";
3304  case ID_VO:
3305  return "Data from VO";
3306  case ID_SIM:
3307  return "Data from SIM";
3308  }
3309  return "Data from Lib Block";
3310 }
3311 
3312 static bool direct_link_id(FileData *fd, Main *main, const int tag, ID *id, ID *id_old)
3313 {
3314  BlendDataReader reader = {fd};
3315 
3316  /* Read part of datablock that is common between real and embedded datablocks. */
3317  direct_link_id_common(&reader, main->curlib, id, id_old, tag);
3318 
3319  if (tag & LIB_TAG_ID_LINK_PLACEHOLDER) {
3320  /* For placeholder we only need to set the tag, no further data to read. */
3321  id->tag = tag;
3322  return true;
3323  }
3324 
3325  const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id);
3326  if (id_type->blend_read_data != NULL) {
3327  id_type->blend_read_data(&reader, id);
3328  }
3329 
3330  /* XXX Very weakly handled currently, see comment in read_libblock() before trying to
3331  * use it for anything new. */
3332  bool success = true;
3333 
3334  switch (GS(id->name)) {
3335  case ID_SCR:
3336  success = BKE_screen_blend_read_data(&reader, (bScreen *)id);
3337  break;
3338  case ID_LI:
3339  direct_link_library(fd, (Library *)id, main);
3340  break;
3341  default:
3342  /* Do nothing. Handled by IDTypeInfo callback. */
3343  break;
3344  }
3345 
3346  /* try to restore (when undoing) or clear ID's cache pointers. */
3347  if (id_type->foreach_cache != NULL) {
3350  }
3351 
3352  return success;
3353 }
3354 
3355 /* Read all data associated with a datablock into datamap. */
3356 static BHead *read_data_into_datamap(FileData *fd, BHead *bhead, const char *allocname)
3357 {
3358  bhead = blo_bhead_next(fd, bhead);
3359 
3360  while (bhead && bhead->code == DATA) {
3361  /* The code below is useful for debugging leaks in data read from the blend file.
3362  * Without this the messages only tell us what ID-type the memory came from,
3363  * eg: `Data from OB len 64`, see #dataname.
3364  * With the code below we get the struct-name to help tracking down the leak.
3365  * This is kept disabled as the #malloc for the text always leaks memory. */
3366 #if 0
3367  {
3368  const short *sp = fd->filesdna->structs[bhead->SDNAnr];
3369  allocname = fd->filesdna->types[sp[0]];
3370  size_t allocname_size = strlen(allocname) + 1;
3371  char *allocname_buf = malloc(allocname_size);
3372  memcpy(allocname_buf, allocname, allocname_size);
3373  allocname = allocname_buf;
3374  }
3375 #endif
3376 
3377  void *data = read_struct(fd, bhead, allocname);
3378  if (data) {
3379  oldnewmap_insert(fd->datamap, bhead->old, data, 0);
3380  }
3381 
3382  bhead = blo_bhead_next(fd, bhead);
3383  }
3384 
3385  return bhead;
3386 }
3387 
3388 /* Verify if the datablock and all associated data is identical. */
3390 {
3391  /* Test ID itself. */
3392  if (bhead->len && !BHEADN_FROM_BHEAD(bhead)->is_memchunk_identical) {
3393  return false;
3394  }
3395 
3396  /* Test any other data that is part of ID (logic must match read_data_into_datamap). */
3397  bhead = blo_bhead_next(fd, bhead);
3398 
3399  while (bhead && bhead->code == DATA) {
3400  if (bhead->len && !BHEADN_FROM_BHEAD(bhead)->is_memchunk_identical) {
3401  return false;
3402  }
3403 
3404  bhead = blo_bhead_next(fd, bhead);
3405  }
3406 
3407  return true;
3408 }
3409 
3410 /* For undo, restore matching library datablock from the old main. */
3412 {
3413  /* In undo case, most libs and linked data should be kept as is from previous state
3414  * (see BLO_read_from_memfile).
3415  * However, some needed by the snapshot being read may have been removed in previous one,
3416  * and would go missing.
3417  * This leads e.g. to disappearing objects in some undo/redo case, see T34446.
3418  * That means we have to carefully check whether current lib or
3419  * libdata already exits in old main, if it does we merely copy it over into new main area,
3420  * otherwise we have to do a full read of that bhead... */
3421  DEBUG_PRINTF("UNDO: restore library %s\n", id->name);
3422 
3423  Main *libmain = fd->old_mainlist->first;
3424  /* Skip oldmain itself... */
3425  for (libmain = libmain->next; libmain; libmain = libmain->next) {
3426  DEBUG_PRINTF(" compare with %s -> ", libmain->curlib ? libmain->curlib->id.name : "<NULL>");
3427  if (libmain->curlib && STREQ(id->name, libmain->curlib->id.name)) {
3428  Main *oldmain = fd->old_mainlist->first;
3429  DEBUG_PRINTF("match!\n");
3430  /* In case of a library, we need to re-add its main to fd->mainlist,
3431  * because if we have later a missing ID_LINK_PLACEHOLDER,
3432  * we need to get the correct lib it is linked to!
3433  * Order is crucial, we cannot bulk-add it in BLO_read_from_memfile()
3434  * like it used to be. */
3435  BLI_remlink(fd->old_mainlist, libmain);
3436  BLI_remlink_safe(&oldmain->libraries, libmain->curlib);
3437  BLI_addtail(fd->mainlist, libmain);
3438  BLI_addtail(&main->libraries, libmain->curlib);
3439  return true;
3440  }
3441  DEBUG_PRINTF("no match\n");
3442  }
3443 
3444  return false;
3445 }
3446 
3447 /* For undo, restore existing linked datablock from the old main. */
3448 static bool read_libblock_undo_restore_linked(FileData *fd, Main *main, const ID *id, BHead *bhead)
3449 {
3450  DEBUG_PRINTF("UNDO: restore linked datablock %s\n", id->name);
3451  DEBUG_PRINTF(" from %s (%s): ",
3452  main->curlib ? main->curlib->id.name : "<NULL>",
3453  main->curlib ? main->curlib->filepath : "<NULL>");
3454 
3455  ID *id_old = BKE_libblock_find_name(main, GS(id->name), id->name + 2);
3456  if (id_old != NULL) {
3457  DEBUG_PRINTF(" found!\n");
3458  /* Even though we found our linked ID, there is no guarantee its address
3459  * is still the same. */
3460  if (id_old != bhead->old) {
3461  oldnewmap_insert(fd->libmap, bhead->old, id_old, GS(id_old->name));
3462  }
3463 
3464  /* No need to do anything else for ID_LINK_PLACEHOLDER, it's assumed
3465  * already present in its lib's main. */
3466  return true;
3467  }
3468 
3469  DEBUG_PRINTF(" not found\n");
3470  return false;
3471 }
3472 
3473 /* For undo, restore unchanged datablock from old main. */
3475  FileData *fd, Main *main, const ID *UNUSED(id), ID *id_old, const int tag)
3476 {
3478  BLI_assert(id_old != NULL);
3479 
3480  /* Some tags need to be preserved here. */
3481  id_old->tag = tag | (id_old->tag & LIB_TAG_EXTRAUSER);
3482  id_old->lib = main->curlib;
3483  id_old->us = ID_FAKE_USERS(id_old);
3484  /* Do not reset id->icon_id here, memory allocated for it remains valid. */
3485  /* Needed because .blend may have been saved with crap value here... */
3486  id_old->newid = NULL;
3487  id_old->orig_id = NULL;
3488 
3489  const short idcode = GS(id_old->name);
3490  Main *old_bmain = fd->old_mainlist->first;
3491  ListBase *old_lb = which_libbase(old_bmain, idcode);
3492  ListBase *new_lb = which_libbase(main, idcode);
3493  BLI_remlink(old_lb, id_old);
3494  BLI_addtail(new_lb, id_old);
3495 
3496  /* Recalc flags, mostly these just remain as they are. */
3498  id_old->recalc_after_undo_push = 0;
3499 
3500  /* As usual, proxies require some special love...
3501  * In `blo_clear_proxy_pointers_from_lib()` we clear all `proxy_from` pointers to local IDs, for
3502  * undo. This is required since we do not re-read linked data in that case, so we also do not
3503  * re-'lib_link' their pointers.
3504  * Those `proxy_from` pointers are then re-defined properly when lib_linking the newly read local
3505  * object. However, in case of re-used data 'as-is', we never lib_link it again, so we have to
3506  * fix those backward pointers here. */
3507  if (GS(id_old->name) == ID_OB) {
3508  Object *ob = (Object *)id_old;
3509  if (ob->proxy != NULL) {
3510  ob->proxy->proxy_from = ob;
3511  }
3512  /* For undo we stay in object mode during undo presses, so keep editmode disabled for re-used
3513  * data-blocks too. */
3514  ob->mode &= ~OB_MODE_EDIT;
3515  }
3516 }
3517 
3518 /* For undo, store changed datablock at old address. */
3520 {
3521  /* During memfile undo, if an ID changed and we cannot directly re-use existing one from old
3522  * bmain, we do a full read of the new id from the memfile, and then fully swap its content
3523  * with the old id. This allows us to keep the same pointer even for modified data, which
3524  * helps reducing further detected changes by the depsgraph (since unchanged IDs remain fully
3525  * unchanged, even if they are using/pointing to a changed one). */
3527  BLI_assert(id_old != NULL);
3528 
3529  const short idcode = GS(id->name);
3530 
3531  Main *old_bmain = fd->old_mainlist->first;
3532  ListBase *old_lb = which_libbase(old_bmain, idcode);
3533  ListBase *new_lb = which_libbase(main, idcode);
3534  BLI_remlink(old_lb, id_old);
3535  BLI_remlink(new_lb, id);
3536 
3537  /* We do not need any remapping from this call here, since no ID pointer is valid in the data
3538  * currently (they are all pointing to old addresses, and need to go through `lib_link`
3539  * process). So we can pass NULL for the Main pointer parameter. */
3540  BKE_lib_id_swap_full(NULL, id, id_old);
3541 
3542  /* Special temporary usage of this pointer, necessary for the `undo_preserve` call after
3543  * lib-linking to restore some data that should never be affected by undo, e.g. the 3D cursor of
3544  * #Scene. */
3545  id_old->orig_id = id;
3546 
3547  BLI_addtail(new_lb, id_old);
3548  BLI_addtail(old_lb, id);
3549 }
3550 
3552  FileData *fd, Main *main, BHead *bhead, const int tag, ID **r_id_old)
3553 {
3554  /* Get pointer to memory of new ID that we will be reading. */
3555  const ID *id = peek_struct_undo(fd, bhead);
3556  const short idcode = GS(id->name);
3557 
3558  if (bhead->code == ID_LI) {
3559  /* Restore library datablock. */
3561  return true;
3562  }
3563  }
3564  else if (bhead->code == ID_LINK_PLACEHOLDER) {
3565  /* Restore linked datablock. */
3566  if (read_libblock_undo_restore_linked(fd, main, id, bhead)) {
3567  return true;
3568  }
3569  }
3570  else if (ELEM(idcode, ID_WM, ID_SCR, ID_WS)) {
3571  /* Skip reading any UI datablocks, existing ones are kept. We don't
3572  * support pointers from other datablocks to UI datablocks so those
3573  * we also don't put UI datablocks in fd->libmap. */
3574  return true;
3575  }
3576 
3577  /* Restore local datablocks. */
3578  DEBUG_PRINTF("UNDO: read %s (uuid %u) -> ", id->name, id->session_uuid);
3579 
3580  ID *id_old = NULL;
3581  const bool do_partial_undo = (fd->skip_flags & BLO_READ_SKIP_UNDO_OLD_MAIN) == 0;
3582  if (do_partial_undo && (bhead->code != ID_LINK_PLACEHOLDER)) {
3583  /* This code should only ever be reached for local data-blocks. */
3584  BLI_assert(main->curlib == NULL);
3585 
3586  /* Find the 'current' existing ID we want to reuse instead of the one we
3587  * would read from the undo memfile. */
3588  BLI_assert(fd->old_idmap != NULL);
3590  }
3591 
3592  if (id_old != NULL && read_libblock_is_identical(fd, bhead)) {
3593  /* Local datablock was unchanged, restore from the old main. */
3594  DEBUG_PRINTF("keep identical datablock\n");
3595 
3596  /* Do not add LIB_TAG_NEW here, this should not be needed/used in undo case anyway (as
3597  * this is only for do_version-like code), but for sake of consistency, and also because
3598  * it will tell us which ID is re-used from old Main, and which one is actually new. */
3599  /* Also do not add LIB_TAG_NEED_LINK, those IDs will never be re-liblinked, hence that tag will
3600  * never be cleared, leading to critical issue in link/append code. */
3601  const int id_tag = tag | LIB_TAG_UNDO_OLD_ID_REUSED;
3602  read_libblock_undo_restore_identical(fd, main, id, id_old, id_tag);
3603 
3604  /* Insert into library map for lookup by newly read datablocks (with pointer value bhead->old).
3605  * Note that existing datablocks in memory (which pointer value would be id_old) are not
3606  * remapped anymore, so no need to store this info here. */
3607  oldnewmap_insert(fd->libmap, bhead->old, id_old, bhead->code);
3608 
3609  *r_id_old = id_old;
3610  return true;
3611  }
3612  if (id_old != NULL) {
3613  /* Local datablock was changed. Restore at the address of the old datablock. */
3614  DEBUG_PRINTF("read to old existing address\n");
3615  *r_id_old = id_old;
3616  return false;
3617  }
3618 
3619  /* Local datablock does not exist in the undo step, so read from scratch. */
3620  DEBUG_PRINTF("read at new address\n");
3621  return false;
3622 }
3623 
3624 /* This routine reads a datablock and its direct data, and advances bhead to
3625  * the next datablock. For library linked datablocks, only a placeholder will
3626  * be generated, to be replaced in read_library_linked_ids.
3627  *
3628  * When reading for undo, libraries, linked datablocks and unchanged datablocks
3629  * will be restored from the old database. Only new or changed datablocks will
3630  * actually be read. */
3632  Main *main,
3633  BHead *bhead,
3634  const int tag,
3635  const bool placeholder_set_indirect_extern,
3636  ID **r_id)
3637 {
3638  /* First attempt to restore existing datablocks for undo.
3639  * When datablocks are changed but still exist, we restore them at the old
3640  * address and inherit recalc flags for the dependency graph. */
3641  ID *id_old = NULL;
3642  if (fd->memfile != NULL) {
3643  if (read_libblock_undo_restore(fd, main, bhead, tag, &id_old)) {
3644  if (r_id) {
3645  *r_id = id_old;
3646  }
3647  return blo_bhead_next(fd, bhead);
3648  }
3649  }
3650 
3651  /* Read libblock struct. */
3652  ID *id = read_struct(fd, bhead, "lib block");
3653  if (id == NULL) {
3654  if (r_id) {
3655  *r_id = NULL;
3656  }
3657  return blo_bhead_next(fd, bhead);
3658  }
3659 
3660  /* Determine ID type and add to main database list. */
3661  const short idcode = GS(id->name);
3662  ListBase *lb = which_libbase(main, idcode);
3663  if (lb == NULL) {
3664  /* Unknown ID type. */
3665  printf("%s: unknown id code '%c%c'\n", __func__, (idcode & 0xff), (idcode >> 8));
3666  MEM_freeN(id);
3667  if (r_id) {
3668  *r_id = NULL;
3669  }
3670  return blo_bhead_next(fd, bhead);
3671  }
3672 
3673  /* NOTE: id must be added to the list before direct_link_id(), since
3674  * direct_link_library() may remove it from there in case of duplicates. */
3675  BLI_addtail(lb, id);
3676 
3677  /* Insert into library map for lookup by newly read datablocks (with pointer value bhead->old).
3678  * Note that existing datablocks in memory (which pointer value would be id_old) are not remapped
3679  * remapped anymore, so no need to store this info here. */
3680  ID *id_target = id_old ? id_old : id;
3681  oldnewmap_insert(fd->libmap, bhead->old, id_target, bhead->code);
3682 
3683  if (r_id) {
3684  *r_id = id_target;
3685  }
3686 
3687  /* Set tag for new datablock to indicate lib linking and versioning needs
3688  * to be done still. */
3689  int id_tag = tag | LIB_TAG_NEED_LINK | LIB_TAG_NEW;
3690 
3691  if (bhead->code == ID_LINK_PLACEHOLDER) {
3692  /* Read placeholder for linked datablock. */
3693  id_tag |= LIB_TAG_ID_LINK_PLACEHOLDER;
3694 
3695  if (placeholder_set_indirect_extern) {
3696  if (id->flag & LIB_INDIRECT_WEAK_LINK) {
3697  id_tag |= LIB_TAG_INDIRECT;
3698  }
3699  else {
3700  id_tag |= LIB_TAG_EXTERN;
3701  }
3702  }
3703 
3704  direct_link_id(fd, main, id_tag, id, id_old);
3705  return blo_bhead_next(fd, bhead);
3706  }
3707 
3708  /* Read datablock contents.
3709  * Use convenient malloc name for debugging and better memory link prints. */
3710  const char *allocname = dataname(idcode);
3711  bhead = read_data_into_datamap(fd, bhead, allocname);
3712  const bool success = direct_link_id(fd, main, id_tag, id, id_old);
3713  oldnewmap_clear(fd->datamap);
3714 
3715  if (!success) {
3716  /* XXX This is probably working OK currently given the very limited scope of that flag.
3717  * However, it is absolutely **not** handled correctly: it is freeing an ID pointer that has
3718  * been added to the fd->libmap mapping, which in theory could lead to nice crashes...
3719  * This should be properly solved at some point. */
3720  BKE_id_free(main, id);
3721  if (r_id != NULL) {
3722  *r_id = NULL;
3723  }
3724  }
3725  else if (id_old) {
3726  /* For undo, store contents read into id at id_old. */
3728  }
3729 
3730  return bhead;
3731 }
3732 
3735 /* -------------------------------------------------------------------- */
3740 {
3742 
3743  bhead = read_data_into_datamap(fd, bhead, "asset-data read");
3744 
3745  BlendDataReader reader = {fd};
3746  BLO_read_data_address(&reader, r_asset_data);
3747  BKE_asset_metadata_read(&reader, *r_asset_data);
3748 
3749  oldnewmap_clear(fd->datamap);
3750 
3751  return bhead;
3752 }
3753 
3756 /* -------------------------------------------------------------------- */
3760 /* note, this has to be kept for reading older files... */
3761 /* also version info is written here */
3762 static BHead *read_global(BlendFileData *bfd, FileData *fd, BHead *bhead)
3763 {
3764  FileGlobal *fg = read_struct(fd, bhead, "Global");
3765 
3766  /* copy to bfd handle */
3767  bfd->main->subversionfile = fg->subversion;
3768  bfd->main->minversionfile = fg->minversion;
3769  bfd->main->minsubversionfile = fg->minsubversion;
3771  BLI_strncpy(bfd->main->build_hash, fg->build_hash, sizeof(bfd->main->build_hash));
3772 
3773  bfd->fileflags = fg->fileflags;
3774  bfd->globalf = fg->globalf;
3775  BLI_strncpy(bfd->filename, fg->filename, sizeof(bfd->filename));
3776 
3777  /* Error in 2.65 and older: main->name was not set if you save from startup
3778  * (not after loading file). */
3779  if (bfd->filename[0] == 0) {
3780  if (fd->fileversion < 265 || (fd->fileversion == 265 && fg->subversion < 1)) {
3781  if ((G.fileflags & G_FILE_RECOVER_READ) == 0) {
3782  BLI_strncpy(bfd->filename, BKE_main_blendfile_path(bfd->main), sizeof(bfd->filename));
3783  }
3784  }
3785 
3786  /* early 2.50 version patch - filename not in FileGlobal struct at all */
3787  if (fd->fileversion <= 250) {
3788  BLI_strncpy(bfd->filename, BKE_main_blendfile_path(bfd->main), sizeof(bfd->filename));
3789  }
3790  }
3791 
3792  if (G.fileflags & G_FILE_RECOVER_READ) {
3793  BLI_strncpy(fd->relabase, fg->filename, sizeof(fd->relabase));
3794  }
3795 
3796  bfd->curscreen = fg->curscreen;
3797  bfd->curscene = fg->curscene;
3798  bfd->cur_view_layer = fg->cur_view_layer;
3799 
3800  MEM_freeN(fg);
3801 
3802  fd->globalf = bfd->globalf;
3803  fd->fileflags = bfd->fileflags;
3804 
3805  return blo_bhead_next(fd, bhead);
3806 }
3807 
3808 /* note, this has to be kept for reading older files... */
3809 static void link_global(FileData *fd, BlendFileData *bfd)
3810 {
3812  bfd->curscreen = newlibadr(fd, NULL, bfd->curscreen);
3813  bfd->curscene = newlibadr(fd, NULL, bfd->curscene);
3814  /* this happens in files older than 2.35 */
3815  if (bfd->curscene == NULL) {
3816  if (bfd->curscreen) {
3817  bfd->curscene = bfd->curscreen->scene;
3818  }
3819  }
3820 }
3821 
3824 /* -------------------------------------------------------------------- */
3829 {
3830  UserDef *user = bfd->user;
3831 
3832  if (user == NULL) {
3833  return;
3834  }
3835 
3837 }
3838 
3839 static void do_versions(FileData *fd, Library *lib, Main *main)
3840 {
3841  /* WATCH IT!!!: pointers from libdata have not been converted */
3842 
3843  /* Don't allow versioning to create new data-blocks. */
3844  main->is_locked_for_linking = true;
3845 
3846  if (G.debug & G_DEBUG) {
3847  char build_commit_datetime[32];
3848  time_t temp_time = main->build_commit_timestamp;
3849  struct tm *tm = (temp_time) ? gmtime(&temp_time) : NULL;
3850  if (LIKELY(tm)) {
3851  strftime(build_commit_datetime, sizeof(build_commit_datetime), "%Y-%m-%d %H:%M", tm);
3852  }
3853  else {
3854  BLI_strncpy(build_commit_datetime, "unknown", sizeof(build_commit_datetime));
3855  }
3856 
3857  printf("read file %s\n Version %d sub %d date %s hash %s\n",
3858  fd->relabase,
3859  main->versionfile,
3860  main->subversionfile,
3861  build_commit_datetime,
3862  main->build_hash);
3863  }
3864 
3872 
3873  /* WATCH IT!!!: pointers from libdata have not been converted yet here! */
3874  /* WATCH IT 2!: Userdef struct init see do_versions_userdef() above! */
3875 
3876  /* don't forget to set version number in BKE_blender_version.h! */
3877 
3878  main->is_locked_for_linking = false;
3879 }
3880 
3882 {
3883  // printf("%s for %s (%s), %d.%d\n", __func__, main->curlib ? main->curlib->filepath :
3884  // main->name, main->curlib ? "LIB" : "MAIN", main->versionfile, main->subversionfile);
3885 
3886  /* Don't allow versioning to create new data-blocks. */
3887  main->is_locked_for_linking = true;
3888 
3895 
3896  main->is_locked_for_linking = false;
3897 }
3898 
3901 /* -------------------------------------------------------------------- */
3905 static void lib_link_all(FileData *fd, Main *bmain)
3906 {
3907  const bool do_partial_undo = (fd->skip_flags & BLO_READ_SKIP_UNDO_OLD_MAIN) == 0;
3908 
3909  BlendLibReader reader = {fd, bmain};
3910 
3911  ID *id;
3912  FOREACH_MAIN_ID_BEGIN (bmain, id) {
3913  if ((id->tag & LIB_TAG_NEED_LINK) == 0) {
3914  /* This ID does not need liblink, just skip to next one. */
3915  continue;
3916  }
3917 
3918  if (fd->memfile != NULL && GS(id->name) == ID_WM) {
3919  /* No load UI for undo memfiles.
3920  * Only WM currently, SCR needs it still (see below), and so does WS? */
3921  continue;
3922  }
3923 
3924  if (fd->memfile != NULL && do_partial_undo && (id->tag & LIB_TAG_UNDO_OLD_ID_REUSED) != 0) {
3925  /* This ID has been re-used from 'old' bmain. Since it was therefore unchanged across
3926  * current undo step, and old IDs re-use their old memory address, we do not need to liblink
3927  * it at all. */
3928  continue;
3929  }
3930 
3931  lib_link_id(&reader, id);
3932 
3933  const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id);
3934  if (id_type->blend_read_lib != NULL) {
3935  id_type->blend_read_lib(&reader, id);
3936  }
3937 
3938  if (GS(id->name) == ID_LI) {
3939  lib_link_library(&reader, (Library *)id); /* Only init users. */
3940  }
3941 
3942  id->tag &= ~LIB_TAG_NEED_LINK;
3943 
3944  /* Some data that should be persistent, like the 3DCursor or the tool settings, are
3945  * stored in IDs affected by undo, like Scene. So this requires some specific handling. */
3946  if (id_type->blend_read_undo_preserve != NULL && id->orig_id != NULL) {
3947  id_type->blend_read_undo_preserve(&reader, id, id->orig_id);
3948  }
3949  }
3951 
3952  /* Cleanup `ID.orig_id`, this is now reserved for depsgraph/COW usage only. */
3953  FOREACH_MAIN_ID_BEGIN (bmain, id) {
3954  id->orig_id = NULL;
3955  }
3957 
3958 #ifndef NDEBUG
3959  /* Double check we do not have any 'need link' tag remaining, this should never be the case once
3960  * this function has run. */
3961  FOREACH_MAIN_ID_BEGIN (bmain, id) {
3962  BLI_assert((id->tag & LIB_TAG_NEED_LINK) == 0);
3963  }
3965 #endif
3966 }
3967 
3974 {
3975  /* We only expect a merged Main here, not a split one. */
3976  BLI_assert((bmain->prev == NULL) && (bmain->next == NULL));
3977 
3978  /* Check for possible cycles in scenes' 'set' background property. */
3980 
3981  /* We could integrate that to mesh/curve/lattice lib_link, but this is really cheap process,
3982  * so simpler to just use it directly in this single call. */
3984 
3985  /* We have to rebuild that runtime information *after* all data-blocks have been properly linked.
3986  */
3988 }
3989 
3992 /* -------------------------------------------------------------------- */
3997 {
3998  BLO_read_data_address(reader, &kmi->properties);
3999  IDP_BlendDataRead(reader, &kmi->properties);
4000  kmi->ptr = NULL;
4001  kmi->flag &= ~KMI_UPDATE;
4002 }
4003 
4004 static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead)
4005 {
4006  UserDef *user;
4007  bfd->user = user = read_struct(fd, bhead, "user def");
4008 
4009  /* User struct has separate do-version handling */
4010  user->versionfile = bfd->main->versionfile;
4011  user->subversionfile = bfd->main->subversionfile;
4012 
4013  /* read all data into fd->datamap */
4014  bhead = read_data_into_datamap(fd, bhead, "user def");
4015 
4016  BlendDataReader reader_ = {fd};
4017  BlendDataReader *reader = &reader_;
4018 
4019  BLO_read_list(reader, &user->themes);
4020  BLO_read_list(reader, &user->user_keymaps);
4021  BLO_read_list(reader, &user->user_keyconfig_prefs);
4022  BLO_read_list(reader, &user->user_menus);
4023  BLO_read_list(reader, &user->addons);
4024  BLO_read_list(reader, &user->autoexec_paths);
4025  BLO_read_list(reader, &user->asset_libraries);
4026 
4027  LISTBASE_FOREACH (wmKeyMap *, keymap, &user->user_keymaps) {
4028  keymap->modal_items = NULL;
4029  keymap->poll = NULL;
4030  keymap->flag &= ~KEYMAP_UPDATE;
4031 
4032  BLO_read_list(reader, &keymap->diff_items);
4033  BLO_read_list(reader, &keymap->items);
4034 
4035  LISTBASE_FOREACH (wmKeyMapDiffItem *, kmdi, &keymap->diff_items) {
4036  BLO_read_data_address(reader, &kmdi->remove_item);
4037  BLO_read_data_address(reader, &kmdi->add_item);
4038 
4039  if (kmdi->remove_item) {
4040  direct_link_keymapitem(reader, kmdi->remove_item);
4041  }
4042  if (kmdi->add_item) {
4043  direct_link_keymapitem(reader, kmdi->add_item);
4044  }
4045  }
4046 
4047  LISTBASE_FOREACH (wmKeyMapItem *, kmi, &keymap->items) {
4048  direct_link_keymapitem(reader, kmi);
4049  }
4050  }
4051 
4053  BLO_read_data_address(reader, &kpt->prop);
4054  IDP_BlendDataRead(reader, &kpt->prop);
4055  }
4056 
4057  LISTBASE_FOREACH (bUserMenu *, um, &user->user_menus) {
4058  BLO_read_list(reader, &um->items);
4059  LISTBASE_FOREACH (bUserMenuItem *, umi, &um->items) {
4060  if (umi->type == USER_MENU_TYPE_OPERATOR) {
4061  bUserMenuItem_Op *umi_op = (bUserMenuItem_Op *)umi;
4062  BLO_read_data_address(reader, &umi_op->prop);
4063  IDP_BlendDataRead(reader, &umi_op->prop);
4064  }
4065  }
4066  }
4067 
4068  LISTBASE_FOREACH (bAddon *, addon, &user->addons) {
4069  BLO_read_data_address(reader, &addon->prop);
4070  IDP_BlendDataRead(reader, &addon->prop);
4071  }
4072 
4073  /* XXX */
4074  user->uifonts.first = user->uifonts.last = NULL;
4075 
4076  BLO_read_list(reader, &user->uistyles);
4077 
4078  /* Don't read the active app template, use the default one. */
4079  user->app_template[0] = '\0';
4080 
4081  /* Clear runtime data. */
4082  user->runtime.is_dirty = false;
4083  user->edit_studio_light = 0;
4084 
4085  /* free fd->datamap again */
4086  oldnewmap_clear(fd->datamap);
4087 
4088  return bhead;
4089 }
4090 
4093 /* -------------------------------------------------------------------- */
4097 BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
4098 {
4099  BHead *bhead = blo_bhead_first(fd);
4100  BlendFileData *bfd;
4101  ListBase mainlist = {NULL, NULL};
4102 
4103  if (fd->memfile != NULL) {
4104  DEBUG_PRINTF("\nUNDO: read step\n");
4105  }
4106 
4107  bfd = MEM_callocN(sizeof(BlendFileData), "blendfiledata");
4108 
4109  bfd->main = BKE_main_new();
4110  bfd->main->versionfile = fd->fileversion;
4111 
4112  bfd->type = BLENFILETYPE_BLEND;
4113 
4114  if ((fd->skip_flags & BLO_READ_SKIP_DATA) == 0) {
4115  BLI_addtail(&mainlist, bfd->main);
4116  fd->mainlist = &mainlist;
4117  BLI_strncpy(bfd->main->name, filepath, sizeof(bfd->main->name));
4118  }
4119 
4120  if (G.background) {
4121  /* We only read & store .blend thumbnail in background mode
4122  * (because we cannot re-generate it, no OpenGL available).
4123  */
4124  const int *data = read_file_thumbnail(fd);
4125 
4126  if (data) {
4127  const int width = data[0];
4128  const int height = data[1];
4130  const size_t sz = BLEN_THUMB_MEMSIZE(width, height);
4131  bfd->main->blen_thumb = MEM_mallocN(sz, __func__);
4132 
4133  BLI_assert((sz - sizeof(*bfd->main->blen_thumb)) ==
4134  (BLEN_THUMB_MEMSIZE_FILE(width, height) - (sizeof(*data) * 2)));
4135  bfd->main->blen_thumb->width = width;
4136  bfd->main->blen_thumb->height = height;
4137  memcpy(bfd->main->blen_thumb->rect, &data[2], sz - sizeof(*bfd->main->blen_thumb));
4138  }
4139  }
4140  }
4141 
4142  while (bhead) {
4143  switch (bhead->code) {
4144  case DATA:
4145  case DNA1:
4146  case TEST: /* used as preview since 2.5x */
4147  case REND:
4148  bhead = blo_bhead_next(fd, bhead);
4149  break;
4150  case GLOB:
4151  bhead = read_global(bfd, fd, bhead);
4152  break;
4153  case USER:
4154  if (fd->skip_flags & BLO_READ_SKIP_USERDEF) {
4155  bhead = blo_bhead_next(fd, bhead);
4156  }
4157  else {
4158  bhead = read_userdef(bfd, fd, bhead);
4159  }
4160  break;
4161  case ENDB:
4162  bhead = NULL;
4163  break;
4164 
4165  case ID_LINK_PLACEHOLDER:
4166  if (fd->skip_flags & BLO_READ_SKIP_DATA) {
4167  bhead = blo_bhead_next(fd, bhead);
4168  }
4169  else {
4170  /* Add link placeholder to the main of the library it belongs to.
4171  * The library is the most recently loaded ID_LI block, according
4172  * to the file format definition. So we can use the entry at the
4173  * end of mainlist, added in direct_link_library. */
4174  Main *libmain = mainlist.last;
4175  bhead = read_libblock(fd, libmain, bhead, 0, true, NULL);
4176  }
4177  break;
4178  /* in 2.50+ files, the file identifier for screens is patched, forward compatibility */
4179  case ID_SCRN:
4180  bhead->code = ID_SCR;
4181  /* pass on to default */
4183  default:
4184  if (fd->skip_flags & BLO_READ_SKIP_DATA) {
4185  bhead = blo_bhead_next(fd, bhead);
4186  }
4187  else {
4188  bhead = read_libblock(fd, bfd->main, bhead, LIB_TAG_LOCAL, false, NULL);
4189  }
4190  }
4191  }
4192 
4193  /* do before read_libraries, but skip undo case */
4194  if (fd->memfile == NULL) {
4195  if ((fd->skip_flags & BLO_READ_SKIP_DATA) == 0) {
4196  do_versions(fd, NULL, bfd->main);
4197  }
4198 
4199  if ((fd->skip_flags & BLO_READ_SKIP_USERDEF) == 0) {
4200  do_versions_userdef(fd, bfd);
4201  }
4202  }
4203 
4204  if ((fd->skip_flags & BLO_READ_SKIP_DATA) == 0) {
4205  read_libraries(fd, &mainlist);
4206 
4207  blo_join_main(&mainlist);
4208 
4209  lib_link_all(fd, bfd->main);
4211 
4212  /* Skip in undo case. */
4213  if (fd->memfile == NULL) {
4214  /* Note that we can't recompute user-counts at this point in undo case, we play too much with
4215  * IDs from different memory realms, and Main database is not in a fully valid state yet.
4216  */
4217  /* Some versioning code does expect some proper user-reference-counting, e.g. in conversion
4218  * from groups to collections... We could optimize out that first call when we are reading a
4219  * current version file, but again this is really not a bottle neck currently.
4220  * So not worth it. */
4221  BKE_main_id_refcount_recompute(bfd->main, false);
4222 
4223  /* Yep, second splitting... but this is a very cheap operation, so no big deal. */
4224  blo_split_main(&mainlist, bfd->main);
4225  LISTBASE_FOREACH (Main *, mainvar, &mainlist) {
4226  BLI_assert(mainvar->versionfile != 0);
4227  do_versions_after_linking(mainvar, fd->reports);
4228  }
4229  blo_join_main(&mainlist);
4230 
4231  /* And we have to compute those user-reference-counts again, as `do_versions_after_linking()`
4232  * does not always properly handle user counts, and/or that function does not take into
4233  * account old, deprecated data. */
4234  BKE_main_id_refcount_recompute(bfd->main, false);
4235 
4236  /* After all data has been read and versioned, uses LIB_TAG_NEW. */
4237  ntreeUpdateAllNew(bfd->main);
4238  }
4239 
4241 
4242  BKE_main_id_tag_all(bfd->main, LIB_TAG_NEW, false);
4243 
4244  /* Now that all our data-blocks are loaded,
4245  * we can re-generate overrides from their references. */
4246  if (fd->memfile == NULL) {
4247  /* Do not apply in undo case! */
4250  }
4251 
4253 
4254  /* Make all relative paths, relative to the open blend file. */
4255  fix_relpaths_library(fd->relabase, bfd->main);
4256 
4257  link_global(fd, bfd); /* as last */
4258  }
4259 
4260  fd->mainlist = NULL; /* Safety, this is local variable, shall not be used afterward. */
4261 
4262  return bfd;
4263 }
4264 
4267 /* -------------------------------------------------------------------- */
4273 struct BHeadSort {
4275  const void *old;
4276 };
4277 
4278 static int verg_bheadsort(const void *v1, const void *v2)
4279 {
4280  const struct BHeadSort *x1 = v1, *x2 = v2;
4281 
4282  if (x1->old > x2->old) {
4283  return 1;
4284  }
4285  if (x1->old < x2->old) {
4286  return -1;
4287  }
4288  return 0;
4289 }
4290 
4292 {
4293  BHead *bhead;
4294  struct BHeadSort *bhs;
4295  int tot = 0;
4296 
4297  for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
4298  tot++;
4299  }
4300 
4301  fd->tot_bheadmap = tot;
4302  if (tot == 0) {
4303  return;
4304  }
4305 
4306  bhs = fd->bheadmap = MEM_malloc_arrayN(tot, sizeof(struct BHeadSort), "BHeadSort");
4307 
4308  for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead), bhs++) {
4309  bhs->bhead = bhead;
4310  bhs->old = bhead->old;
4311  }
4312 
4313  qsort(fd->bheadmap, tot, sizeof(struct BHeadSort), verg_bheadsort);
4314 }
4315 
4317 {
4318  /* Skip library data-blocks in undo, see comment in read_libblock. */
4319  if (fd->memfile) {
4320  return NULL;
4321  }
4322 
4323  for (; bhead; bhead = blo_bhead_prev(fd, bhead)) {
4324  if (bhead->code == ID_LI) {
4325  break;
4326  }
4327  }
4328 
4329  return bhead;
4330 }
4331 
4332 static BHead *find_bhead(FileData *fd, void *old)
4333 {
4334 #if 0
4335  BHead* bhead;
4336 #endif
4337  struct BHeadSort *bhs, bhs_s;
4338 
4339  if (!old) {
4340  return NULL;
4341  }
4342 
4343  if (fd->bheadmap == NULL) {
4344  sort_bhead_old_map(fd);
4345  }
4346 
4347  bhs_s.old = old;
4348  bhs = bsearch(&bhs_s, fd->bheadmap, fd->tot_bheadmap, sizeof(struct BHeadSort), verg_bheadsort);
4349 
4350  if (bhs) {
4351  return bhs->bhead;
4352  }
4353 
4354 #if 0
4355  for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
4356  if (bhead->old == old) {
4357  return bhead;
4358  }
4359  }
4360 #endif
4361 
4362  return NULL;
4363 }
4364 
4365 static BHead *find_bhead_from_code_name(FileData *fd, const short idcode, const char *name)
4366 {
4367 #ifdef USE_GHASH_BHEAD
4368 
4369  char idname_full[MAX_ID_NAME];
4370 
4371  *((short *)idname_full) = idcode;
4372  BLI_strncpy(idname_full + 2, name, sizeof(idname_full) - 2);
4373 
4374  return BLI_ghash_lookup(fd->bhead_idname_hash, idname_full);
4375 
4376 #else
4377  BHead *bhead;
4378 
4379  for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
4380  if (bhead->code == idcode) {
4381  const char *idname_test = blo_bhead_id_name(fd, bhead);
4382  if (STREQ(idname_test + 2, name)) {
4383  return bhead;
4384  }
4385  }
4386  else if (bhead->code == ENDB) {
4387  break;
4388  }
4389  }
4390 
4391  return NULL;
4392 #endif
4393 }
4394 
4395 static BHead *find_bhead_from_idname(FileData *fd, const char *idname)
4396 {
4397 #ifdef USE_GHASH_BHEAD
4398  return BLI_ghash_lookup(fd->bhead_idname_hash, idname);
4399 #else
4400  return find_bhead_from_code_name(fd, GS(idname), idname + 2);
4401 #endif
4402 }
4403 
4404 static ID *is_yet_read(FileData *fd, Main *mainvar, BHead *bhead)
4405 {
4406  const char *idname = blo_bhead_id_name(fd, bhead);
4407  /* which_libbase can be NULL, intentionally not using idname+2 */
4408  return BLI_findstring(which_libbase(mainvar, GS(idname)), idname, offsetof(ID, name));
4409 }
4410 
4413 /* -------------------------------------------------------------------- */
4417 static void expand_doit_library(void *fdhandle, Main *mainvar, void *old)
4418 {
4419  FileData *fd = fdhandle;
4420 
4421  BHead *bhead = find_bhead(fd, old);
4422  if (bhead == NULL) {
4423  return;
4424  }
4425 
4426  if (bhead->code == ID_LINK_PLACEHOLDER) {
4427  /* Placeholder link to data-lock in another library. */
4428  BHead *bheadlib = find_previous_lib(fd, bhead);
4429  if (bheadlib == NULL) {
4430  return;
4431  }
4432 
4433  Library *lib = read_struct(fd, bheadlib, "Library");
4434  Main *libmain = blo_find_main(fd, lib->filepath, fd->relabase);
4435 
4436  if (libmain->curlib == NULL) {
4437  const char *idname = blo_bhead_id_name(fd, bhead);
4438 
4440  RPT_WARNING,
4441  TIP_("LIB: Data refers to main .blend file: '%s' from %s"),
4442  idname,
4443  mainvar->curlib->filepath_abs);
4444  return;
4445  }
4446 
4447  ID *id = is_yet_read(fd, libmain, bhead);
4448 
4449  if (id == NULL) {
4450  /* ID has not been read yet, add placeholder to the main of the
4451  * library it belongs to, so that it will be read later. */
4452  read_libblock(fd, libmain, bhead, fd->id_tag_extra | LIB_TAG_INDIRECT, false, NULL);
4453  /* commented because this can print way too much */
4454  // if (G.debug & G_DEBUG) printf("expand_doit: other lib %s\n", lib->filepath);
4455 
4456  /* for outliner dependency only */
4457  libmain->curlib->parent = mainvar->curlib;
4458  }
4459  else {
4460  /* Convert any previously read weak link to regular link
4461  * to signal that we want to read this data-block. */
4463  id->flag &= ~LIB_INDIRECT_WEAK_LINK;
4464  }
4465 
4466  /* "id" is either a placeholder or real ID that is already in the
4467  * main of the library (A) it belongs to. However it might have been
4468  * put there by another library (C) which only updated its own
4469  * fd->libmap. In that case we also need to update the fd->libmap
4470  * of the current library (B) so we can find it for lookups.
4471  *
4472  * An example of such a setup is:
4473  * (A) tree.blend: contains Tree object.
4474  * (B) forest.blend: contains Forest collection linking in Tree from tree.blend.
4475  * (C) shot.blend: links in both Tree from tree.blend and Forest from forest.blend.
4476  */
4477  oldnewmap_insert(fd->libmap, bhead->old, id, bhead->code);
4478 
4479  /* If "id" is a real data-lock and not a placeholder, we need to
4480  * update fd->libmap to replace ID_LINK_PLACEHOLDER with the real
4481  * ID_* code.
4482  *
4483  * When the real ID is read this replacement happens for all
4484  * libraries read so far, but not for libraries that have not been
4485  * read yet at that point. */
4487 
4488  /* Commented because this can print way too much. */
4489 #if 0
4490  if (G.debug & G_DEBUG) {
4491  printf("expand_doit: already linked: %s lib: %s\n", id->name, lib->filepath);
4492  }
4493 #endif
4494  }
4495 
4496  MEM_freeN(lib);
4497  }
4498  else {
4499  /* Data-block in same library. */
4500  /* In 2.50+ file identifier for screens is patched, forward compatibility. */
4501  if (bhead->code == ID_SCRN) {
4502  bhead->code = ID_SCR;
4503  }
4504 
4505  ID *id = is_yet_read(fd, mainvar, bhead);
4506  if (id == NULL) {
4507  read_libblock(fd,
4508  mainvar,
4509  bhead,
4511  false,
4512  NULL);
4513  }
4514  else {
4515  /* Convert any previously read weak link to regular link
4516  * to signal that we want to read this data-block. */
4518  id->flag &= ~LIB_INDIRECT_WEAK_LINK;
4519  }
4520 
4521  /* this is actually only needed on UI call? when ID was already read before,
4522  * and another append happens which invokes same ID...
4523  * in that case the lookup table needs this entry */
4524  oldnewmap_insert(fd->libmap, bhead->old, id, bhead->code);
4525  /* commented because this can print way too much */
4526  // if (G.debug & G_DEBUG) printf("expand: already read %s\n", id->name);
4527  }
4528  }
4529 }
4530 
4532 
4533 static void expand_id(BlendExpander *expander, ID *id);
4534 
4535 static void expand_id_embedded_id(BlendExpander *expander, ID *id)
4536 {
4537  /* Handle 'private IDs'. */
4538  bNodeTree *nodetree = ntreeFromID(id);
4539  if (nodetree != NULL) {
4540  expand_id(expander, &nodetree->id);
4541  ntreeBlendReadExpand(expander, nodetree);
4542  }
4543 
4544  if (GS(id->name) == ID_SCE) {
4545  Scene *scene = (Scene *)id;
4546  if (scene->master_collection != NULL) {
4547  expand_id(expander, &scene->master_collection->id);
4549  }
4550  }
4551 }
4552 
4553 static void expand_id(BlendExpander *expander, ID *id)
4554 {
4555  IDP_BlendReadExpand(expander, id->properties);
4556 
4557  if (id->override_library) {
4558  BLO_expand(expander, id->override_library->reference);
4559  BLO_expand(expander, id->override_library->storage);
4560  }
4561 
4562  AnimData *adt = BKE_animdata_from_id(id);
4563  if (adt != NULL) {
4564  BKE_animdata_blend_read_expand(expander, adt);
4565  }
4566 
4567  expand_id_embedded_id(expander, id);
4568 }
4569 
4576 {
4577  expand_doit = expand_doit_func;
4578 }
4579 
4587 void BLO_expand_main(void *fdhandle, Main *mainvar)
4588 {
4589  ListBase *lbarray[INDEX_ID_MAX];
4590  FileData *fd = fdhandle;
4591  ID *id;
4592  int a;
4593  bool do_it = true;
4594 
4595  BlendExpander expander = {fd, mainvar};
4596 
4597  while (do_it) {
4598  do_it = false;
4599 
4600  a = set_listbasepointers(mainvar, lbarray);
4601  while (a--) {
4602  id = lbarray[a]->first;
4603  while (id) {
4604  if (id->tag & LIB_TAG_NEED_EXPAND) {
4605  expand_id(&expander, id);
4606 
4607  const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id);
4608  if (id_type->blend_read_expand != NULL) {
4609  id_type->blend_read_expand(&expander, id);
4610  }
4611 
4612  do_it = true;
4613  id->tag &= ~LIB_TAG_NEED_EXPAND;
4614  }
4615  id = id->next;
4616  }
4617  }
4618  }
4619 }
4620 
4623 /* -------------------------------------------------------------------- */
4627 static bool object_in_any_scene(Main *bmain, Object *ob)
4628 {
4629  LISTBASE_FOREACH (Scene *, sce, &bmain->scenes) {
4630  if (BKE_scene_object_find(sce, ob)) {
4631  return true;
4632  }
4633  }
4634 
4635  return false;
4636 }
4637 
4638 static bool object_in_any_collection(Main *bmain, Object *ob)
4639 {
4640  LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
4641  if (BKE_collection_has_object(collection, ob)) {
4642  return true;
4643  }
4644  }
4645 
4646  LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4647  if (scene->master_collection != NULL &&
4649  return true;
4650  }
4651  }
4652 
4653  return false;
4654 }
4655 
4660  Object *ob, bool set_selected, bool set_active, ViewLayer *view_layer, const View3D *v3d)
4661 {
4662  Base *base = BKE_view_layer_base_find(view_layer, ob);
4663 
4664  if (v3d != NULL) {
4665  base->local_view_bits |= v3d->local_view_uuid;
4666  }
4667 
4668  if (set_selected) {
4669  if (base->flag & BASE_SELECTABLE) {
4670  base->flag |= BASE_SELECTED;
4671  }
4672  }
4673 
4674  if (set_active) {
4675  view_layer->basact = base;
4676  }
4677 
4679 }
4680 
4681 static void add_loose_objects_to_scene(Main *mainvar,
4682  Main *bmain,
4683  Scene *scene,
4684  ViewLayer *view_layer,
4685  const View3D *v3d,
4686  Library *lib,
4687  const short flag)
4688 {
4689  Collection *active_collection = NULL;
4690  const bool do_append = (flag & FILE_LINK) == 0;
4691 
4692  BLI_assert(scene);
4693 
4694  /* Give all objects which are LIB_TAG_INDIRECT a base,
4695  * or for a collection when *lib has been set. */
4696  LISTBASE_FOREACH (Object *, ob, &mainvar->objects) {
4697  bool do_it = (ob->id.tag & LIB_TAG_DOIT) != 0;
4698  if (do_it || ((ob->id.tag & LIB_TAG_INDIRECT) && (ob->id.tag & LIB_TAG_PRE_EXISTING) == 0)) {
4699  if (do_append) {
4700  if (ob->id.us == 0) {
4701  do_it = true;
4702  }
4703  else if ((ob->id.lib == lib) && !object_in_any_collection(bmain, ob)) {
4704  /* When appending, make sure any indirectly loaded object gets a base,
4705  * when they are not part of any collection yet. */
4706  do_it = true;
4707  }
4708  }
4709 
4710  if (do_it) {
4711  /* Find or add collection as needed. */
4712  if (active_collection == NULL) {
4713  if (flag & FILE_ACTIVE_COLLECTION) {
4715  active_collection = lc->collection;
4716  }
4717  else {
4718  active_collection = BKE_collection_add(bmain, scene->master_collection, NULL);
4719  }
4720  }
4721 
4722  CLAMP_MIN(ob->id.us, 0);
4723  ob->mode = OB_MODE_OBJECT;
4724 
4725  BKE_collection_object_add(bmain, active_collection, ob);
4726 
4727  const bool set_selected = (flag & FILE_AUTOSELECT) != 0;
4728  /* Do NOT make base active here! screws up GUI stuff,
4729  * if you want it do it at the editor level. */
4730  const bool set_active = false;
4731  object_base_instance_init(ob, set_selected, set_active, view_layer, v3d);
4732 
4733  ob->id.tag &= ~LIB_TAG_INDIRECT;
4734  ob->id.flag &= ~LIB_INDIRECT_WEAK_LINK;
4735  ob->id.tag |= LIB_TAG_EXTERN;
4736  }
4737  }
4738  }
4739 }
4740 
4742  Main *bmain,
4743  Scene *scene,
4744  ViewLayer *view_layer,
4745  const View3D *v3d,
4746  const short flag)
4747 {
4748  if ((flag & FILE_OBDATA_INSTANCE) == 0) {
4749  return;
4750  }
4751 
4752  Collection *active_collection = scene->master_collection;
4753  if (flag & FILE_ACTIVE_COLLECTION) {
4755  active_collection = lc->collection;
4756  }
4757 
4758  /* Loop over all ID types, instancing object-data for ID types that have support for it. */
4759  ListBase *lbarray[INDEX_ID_MAX];
4760  int i = set_listbasepointers(mainvar, lbarray);
4761  while (i--) {
4762  const short idcode = BKE_idtype_idcode_from_index(i);
4763  if (!OB_DATA_SUPPORT_ID(idcode)) {
4764  continue;
4765  }
4766 
4767  LISTBASE_FOREACH (ID *, id, lbarray[i]) {
4768  if (id->tag & LIB_TAG_DOIT) {
4769  const int type = BKE_object_obdata_to_type(id);
4770  BLI_assert(type != -1);
4771  Object *ob = BKE_object_add_only_object(bmain, type, id->name + 2);
4772  ob->data = id;
4773  id_us_plus(id);
4774  BKE_object_materials_test(bmain, ob, ob->data);
4775 
4776  BKE_collection_object_add(bmain, active_collection, ob);
4777 
4778  const bool set_selected = (flag & FILE_AUTOSELECT) != 0;
4779  /* Do NOT make base active here! screws up GUI stuff,
4780  * if you want it do it at the editor level. */
4781  bool set_active = false;
4782  object_base_instance_init(ob, set_selected, set_active, view_layer, v3d);
4783 
4785  }
4786  }
4787  }
4788 }
4789 
4790 static void add_collections_to_scene(Main *mainvar,
4791  Main *bmain,
4792  Scene *scene,
4793  ViewLayer *view_layer,
4794  const View3D *v3d,
4795  Library *lib,
4796  const short flag)
4797 {
4798  Collection *active_collection = scene->master_collection;
4799  if (flag & FILE_ACTIVE_COLLECTION) {
4801  active_collection = lc->collection;
4802  }
4803 
4804  /* Give all objects which are tagged a base. */
4805  LISTBASE_FOREACH (Collection *, collection, &mainvar->collections) {
4806  if ((flag & FILE_COLLECTION_INSTANCE) && (collection->id.tag & LIB_TAG_DOIT)) {
4807  /* Any indirect collection should not have been tagged. */
4808  BLI_assert((collection->id.tag & LIB_TAG_INDIRECT) == 0);
4809 
4810  /* BKE_object_add(...) messes with the selection. */
4811  Object *ob = BKE_object_add_only_object(bmain, OB_EMPTY, collection->id.name + 2);
4812  ob->type = OB_EMPTY;
4813  ob->empty_drawsize = U.collection_instance_empty_size;
4814 
4815  BKE_collection_object_add(bmain, active_collection, ob);
4816 
4817  const bool set_selected = (flag & FILE_AUTOSELECT) != 0;
4818  /* TODO: why is it OK to make this active here but not in other situations?
4819  * See other callers of #object_base_instance_init */
4820  const bool set_active = set_selected;
4821  object_base_instance_init(ob, set_selected, set_active, view_layer, v3d);
4822 
4824 
4825  /* Assign the collection. */
4826  ob->instance_collection = collection;
4827  id_us_plus(&collection->id);
4830  }
4831  /* We do not want to force instantiation of indirectly linked collections,
4832  * not even when appending. Users can now easily instantiate collections (and their objects)
4833  * as needed by themselves. See T67032. */
4834  else if ((collection->id.tag & LIB_TAG_INDIRECT) == 0) {
4835  bool do_add_collection = (collection->id.tag & LIB_TAG_DOIT) != 0;
4836  if (!do_add_collection) {
4837  /* We need to check that objects in that collections are already instantiated in a scene.
4838  * Otherwise, it's better to add the collection to the scene's active collection, than to
4839  * instantiate its objects in active scene's collection directly. See T61141.
4840  * Note that we only check object directly into that collection,
4841  * not recursively into its children.
4842  */
4843  LISTBASE_FOREACH (CollectionObject *, coll_ob, &collection->gobject) {
4844  Object *ob = coll_ob->ob;
4845  if ((ob->id.tag & (LIB_TAG_PRE_EXISTING | LIB_TAG_DOIT | LIB_TAG_INDIRECT)) == 0 &&
4846  (ob->id.lib == lib) && (object_in_any_scene(bmain, ob) == 0)) {
4847  do_add_collection = true;
4848  break;
4849  }
4850  }
4851  }
4852  if (do_add_collection) {
4853  /* Add collection as child of active collection. */
4854  BKE_collection_child_add(bmain, active_collection, collection);
4855 
4856  if (flag & FILE_AUTOSELECT) {
4857  LISTBASE_FOREACH (CollectionObject *, coll_ob, &collection->gobject) {
4858  Object *ob = coll_ob->ob;
4859  Base *base = BKE_view_layer_base_find(view_layer, ob);
4860  if (base) {
4861  base->flag |= BASE_SELECTED;
4863  }
4864  }
4865  }
4866 
4867  /* Those are kept for safety and consistency, but should not be needed anymore? */
4868  collection->id.tag &= ~LIB_TAG_INDIRECT;
4869  collection->id.flag &= ~LIB_INDIRECT_WEAK_LINK;
4870  collection->id.tag |= LIB_TAG_EXTERN;
4871  }
4872  }
4873  }
4874 }
4875 
4876 /* returns true if the item was found
4877  * but it may already have already been appended/linked */
4879  Main *mainl, FileData *fd, const short idcode, const char *name, const int flag)
4880 {
4881  BHead *bhead = find_bhead_from_code_name(fd, idcode, name);
4882  ID *id;
4883 
4884  const bool use_placeholders = (flag & BLO_LIBLINK_USE_PLACEHOLDERS) != 0;
4885  const bool force_indirect = (flag & BLO_LIBLINK_FORCE_INDIRECT) != 0;
4886 
4888 
4889  if (bhead) {
4890  id = is_yet_read(fd, mainl, bhead);
4891  if (id == NULL) {
4892  /* not read yet */
4893  const int tag = ((force_indirect ? LIB_TAG_INDIRECT : LIB_TAG_EXTERN) | fd->id_tag_extra);
4894  read_libblock(fd, mainl, bhead, tag | LIB_TAG_NEED_EXPAND, false, &id);
4895 
4896  if (id) {
4897  /* sort by name in list */
4898  ListBase *lb = which_libbase(mainl, idcode);
4899  id_sort_by_name(lb, id, NULL);
4900  }
4901  }
4902  else {
4903  /* already linked */
4904  if (G.debug) {
4905  printf("append: already linked\n");
4906  }
4907  oldnewmap_insert(fd->libmap, bhead->old, id, bhead->code);
4908  if (!force_indirect && (id->tag & LIB_TAG_INDIRECT)) {
4909  id->tag &= ~LIB_TAG_INDIRECT;
4910  id->flag &= ~LIB_INDIRECT_WEAK_LINK;
4911  id->tag |= LIB_TAG_EXTERN;
4912  }
4913  }
4914  }
4915  else if (use_placeholders) {
4916  /* XXX flag part is weak! */
4917  id = create_placeholder(
4918  mainl, idcode, name, force_indirect ? LIB_TAG_INDIRECT : LIB_TAG_EXTERN);
4919  }
4920  else {
4921  id = NULL;
4922  }
4923 
4924  /* if we found the id but the id is NULL, this is really bad */
4925  BLI_assert(!((bhead != NULL) && (id == NULL)));
4926 
4927  /* Tag as loose object (or data associated with objects)
4928  * needing to be instantiated in #LibraryLink_Params.scene. */
4929  if ((id != NULL) && (flag & BLO_LIBLINK_NEEDS_ID_TAG_DOIT)) {
4930  if (library_link_idcode_needs_tag_check(idcode, flag)) {
4931  id->tag |= LIB_TAG_DOIT;
4932  }
4933  }
4934 
4935  return id;
4936 }
4937 
4941 int BLO_library_link_copypaste(Main *mainl, BlendHandle *bh, const uint64_t id_types_mask)
4942 {
4943  FileData *fd = (FileData *)(bh);
4944  BHead *bhead;
4945  int num_directly_linked = 0;
4946 
4947  for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
4948  ID *id = NULL;
4949 
4950  if (bhead->code == ENDB) {
4951  break;
4952  }
4953 
4955  (id_types_mask == 0 ||
4956  (BKE_idtype_idcode_to_idfilter((short)bhead->code) & id_types_mask) != 0)) {
4957  read_libblock(fd, mainl, bhead, LIB_TAG_NEED_EXPAND | LIB_TAG_INDIRECT, false, &id);
4958  num_directly_linked++;
4959  }
4960 
4961  if (id) {
4962  /* sort by name in list */
4963  ListBase *lb = which_libbase(mainl, GS(id->name));
4964  id_sort_by_name(lb, id, NULL);
4965 
4966  if (bhead->code == ID_OB) {
4967  /* Instead of instancing Base's directly, postpone until after collections are loaded
4968  * otherwise the base's flag is set incorrectly when collections are used */
4969  Object *ob = (Object *)id;
4970  ob->mode = OB_MODE_OBJECT;
4971  /* ensure add_loose_objects_to_scene runs on this object */
4972  BLI_assert(id->us == 0);
4973  }
4974  }
4975  }
4976 
4977  return num_directly_linked;
4978 }
4979 
4990  BlendHandle **bh,
4991  const short idcode,
4992  const char *name,
4993  const struct LibraryLink_Params *params)
4994 {
4995  FileData *fd = (FileData *)(*bh);
4996  return link_named_part(mainl, fd, idcode, name, params->flag);
4997 }
4998 
4999 /* common routine to append/link something from a library */
5000 
5004 static bool library_link_idcode_needs_tag_check(const short idcode, const int flag)
5005 {
5006  if (flag & BLO_LIBLINK_NEEDS_ID_TAG_DOIT) {
5007  /* Always true because of #add_loose_objects_to_scene & #add_collections_to_scene. */
5008  if (ELEM(idcode, ID_OB, ID_GR)) {
5009  return true;
5010  }
5011  if (flag & FILE_OBDATA_INSTANCE) {
5012  if (OB_DATA_SUPPORT_ID(idcode)) {
5013  return true;
5014  }
5015  }
5016  }
5017  return false;
5018 }
5019 
5023 static void library_link_clear_tag(Main *mainvar, const int flag)
5024 {
5025  for (int i = 0; i < INDEX_ID_MAX; i++) {
5026  const short idcode = BKE_idtype_idcode_from_index(i);
5027  BLI_assert(idcode != -1);
5028  if (library_link_idcode_needs_tag_check(idcode, flag)) {
5029  BKE_main_id_tag_idcode(mainvar, idcode, LIB_TAG_DOIT, false);
5030  }
5031  }
5032 }
5033 
5035  Main *mainvar, FileData **fd, const char *filepath, const int flag, const int id_tag_extra)
5036 {
5037  Main *mainl;
5038 
5039  /* Only allow specific tags to be set as extra,
5040  * otherwise this could conflict with library loading logic.
5041  * Other flags can be added here, as long as they are safe. */
5042  BLI_assert((id_tag_extra & ~LIB_TAG_TEMP_MAIN) == 0);
5043 
5044  (*fd)->id_tag_extra = id_tag_extra;
5045 
5046  (*fd)->mainlist = MEM_callocN(sizeof(ListBase), "FileData.mainlist");
5047 
5048  if (flag & BLO_LIBLINK_NEEDS_ID_TAG_DOIT) {
5049  /* Clear for objects and collections instantiating tag. */
5050  library_link_clear_tag(mainvar, flag);
5051  }
5052 
5053  /* make mains */
5054  blo_split_main((*fd)->mainlist, mainvar);
5055 
5056  /* which one do we need? */
5057  mainl = blo_find_main(*fd, filepath, BKE_main_blendfile_path(mainvar));
5058 
5059  /* needed for do_version */
5060  mainl->versionfile = (*fd)->fileversion;
5061  read_file_version(*fd, mainl);
5062 #ifdef USE_GHASH_BHEAD
5064 #endif
5065 
5066  return mainl;
5067 }
5068 
5070  struct Main *bmain,
5071  const int flag,
5072  const int id_tag_extra)
5073 {
5074  memset(params, 0, sizeof(*params));
5075  params->bmain = bmain;
5076  params->flag = flag;
5077  params->id_tag_extra = id_tag_extra;
5078 }
5079 
5081  struct Main *bmain,
5082  const int flag,
5083  const int id_tag_extra,
5084  /* Context arguments. */
5085  struct Scene *scene,
5086  struct ViewLayer *view_layer,
5087  const struct View3D *v3d)
5088 {
5089  BLO_library_link_params_init(params, bmain, flag, id_tag_extra);
5090  if (scene != NULL) {
5091  /* Tagging is needed for instancing. */
5093 
5094  params->context.scene = scene;
5095  params->context.view_layer = view_layer;
5096  params->context.v3d = v3d;
5097  }
5098 }
5099 
5110  const char *filepath,
5111  const struct LibraryLink_Params *params)
5112 {
5113  FileData *fd = (FileData *)(*bh);
5114  return library_link_begin(params->bmain, &fd, filepath, params->flag, params->id_tag_extra);
5115 }
5116 
5117 static void split_main_newid(Main *mainptr, Main *main_newid)
5118 {
5119  /* We only copy the necessary subset of data in this temp main. */
5120  main_newid->versionfile = mainptr->versionfile;
5121  main_newid->subversionfile = mainptr->subversionfile;
5122  BLI_strncpy(main_newid->name, mainptr->name, sizeof(main_newid->name));
5123  main_newid->curlib = mainptr->curlib;
5124 
5125  ListBase *lbarray[INDEX_ID_MAX];
5126  ListBase *lbarray_newid[INDEX_ID_MAX];
5127  int i = set_listbasepointers(mainptr, lbarray);
5128  set_listbasepointers(main_newid, lbarray_newid);
5129  while (i--) {
5130  BLI_listbase_clear(lbarray_newid[i]);
5131 
5132  LISTBASE_FOREACH_MUTABLE (ID *, id, lbarray[i]) {
5133  if (id->tag & LIB_TAG_NEW) {
5134  BLI_remlink(lbarray[i], id);
5135  BLI_addtail(lbarray_newid[i], id);
5136  }
5137  }
5138  }
5139 }
5140 
5147 static void library_link_end(Main *mainl,
5148  FileData **fd,
5149  Main *bmain,
5150  const int flag,
5151  Scene *scene,
5152  ViewLayer *view_layer,
5153  const View3D *v3d)
5154 {
5155  Main *mainvar;
5156  Library *curlib;
5157 
5158  /* expander now is callback function */
5160 
5161  /* make main consistent */
5162  BLO_expand_main(*fd, mainl);
5163 
5164  /* do this when expand found other libs */
5165  read_libraries(*fd, (*fd)->mainlist);
5166 
5167  curlib = mainl->curlib;
5168 
5169  /* make the lib path relative if required */
5170  if (flag & FILE_RELPATH) {
5171  /* use the full path, this could have been read by other library even */
5172  BLI_strncpy(curlib->filepath, curlib->filepath_abs, sizeof(curlib->filepath));
5173 
5174  /* uses current .blend file as reference */
5176  }
5177 
5178  blo_join_main((*fd)->mainlist);
5179  mainvar = (*fd)->mainlist->first;
5180  mainl = NULL; /* blo_join_main free's mainl, cant use anymore */
5181 
5182  lib_link_all(*fd, mainvar);
5184 
5185  /* Some versioning code does expect some proper userrefcounting, e.g. in conversion from
5186  * groups to collections... We could optimize out that first call when we are reading a
5187  * current version file, but again this is really not a bottle neck currently. so not worth
5188  * it. */
5189  BKE_main_id_refcount_recompute(mainvar, false);
5190 
5192 
5193  /* Yep, second splitting... but this is a very cheap operation, so no big deal. */
5194  blo_split_main((*fd)->mainlist, mainvar);
5195  Main *main_newid = BKE_main_new();
5196  for (mainvar = ((Main *)(*fd)->mainlist->first)->next; mainvar; mainvar = mainvar->next) {
5197  BLI_assert(mainvar->versionfile != 0);
5198  /* We need to split out IDs already existing,
5199  * or they will go again through do_versions - bad, very bad! */
5200  split_main_newid(mainvar, main_newid);
5201 
5202  do_versions_after_linking(main_newid, (*fd)->reports);
5203 
5204  add_main_to_main(mainvar, main_newid);
5205  }
5206 
5207  BKE_main_free(main_newid);
5208  blo_join_main((*fd)->mainlist);
5209  mainvar = (*fd)->mainlist->first;
5210  MEM_freeN((*fd)->mainlist);
5211 
5212  /* This does not take into account old, deprecated data, so we also have to do it after
5213  * `do_versions_after_linking()`. */
5214  BKE_main_id_refcount_recompute(mainvar, false);
5215 
5216  /* After all data has been read and versioned, uses LIB_TAG_NEW. */
5217  ntreeUpdateAllNew(mainvar);
5218 
5219  placeholders_ensure_valid(mainvar);
5220 
5221  BKE_main_id_tag_all(mainvar, LIB_TAG_NEW, false);
5222 
5223  /* Make all relative paths, relative to the open blend file. */
5224  fix_relpaths_library(BKE_main_blendfile_path(mainvar), mainvar);
5225 
5226  /* Give a base to loose objects and collections.
5227  * Only directly linked objects & collections are instantiated by
5228  * #BLO_library_link_named_part & co,
5229  * here we handle indirect ones and other possible edge-cases. */
5230  if (flag & BLO_LIBLINK_NEEDS_ID_TAG_DOIT) {
5231  /* Should always be true. */
5232  if (scene != NULL) {
5233  add_collections_to_scene(mainvar, bmain, scene, view_layer, v3d, curlib, flag);
5234  add_loose_objects_to_scene(mainvar, bmain, scene, view_layer, v3d, curlib, flag);
5235  add_loose_object_data_to_scene(mainvar, bmain, scene, view_layer, v3d, flag);
5236  }
5237 
5238  /* Clear objects and collections instantiating tag. */
5239  library_link_clear_tag(mainvar, flag);
5240  }
5241 
5242  /* patch to prevent switch_endian happens twice */
5243  if ((*fd)->flags & FD_FLAGS_SWITCH_ENDIAN) {
5244  blo_filedata_free(*fd);
5245  *fd = NULL;
5246  }
5247 }
5248 
5259 {
5260  FileData *fd = (FileData *)(*bh);
5261  library_link_end(mainl,
5262  &fd,
5263  params->bmain,
5264  params->flag,
5265  params->context.scene,
5266  params->context.view_layer,
5267  params->context.v3d);
5268  *bh = (BlendHandle *)fd;
5269 }
5270 
5271 void *BLO_library_read_struct(FileData *fd, BHead *bh, const char *blockname)
5272 {
5273  return read_struct(fd, bh, blockname);
5274 }
5275 
5278 /* -------------------------------------------------------------------- */
5282 static int has_linked_ids_to_read(Main *mainvar)
5283 {
5284  ListBase *lbarray[INDEX_ID_MAX];
5285  int a = set_listbasepointers(mainvar, lbarray);
5286 
5287  while (a--) {
5288  LISTBASE_FOREACH (ID *, id, lbarray[a]) {
5290  return true;
5291  }
5292  }
5293  }
5294 
5295  return false;
5296 }
5297 
5299  FileData *basefd, FileData *fd, Main *mainvar, ID *id, ID **r_id)
5300 {
5301  BHead *bhead = NULL;
5302  const bool is_valid = BKE_idtype_idcode_is_linkable(GS(id->name)) ||
5303  ((id->tag & LIB_TAG_EXTERN) == 0);
5304 
5305  if (fd) {
5307  }
5308 
5309  if (!is_valid) {
5310  BLO_reportf_wrap(basefd->reports,
5311  RPT_ERROR,
5312  TIP_("LIB: %s: '%s' is directly linked from '%s' (parent '%s'), but is a "
5313  "non-linkable data type"),
5315  id->name + 2,
5316  mainvar->curlib->filepath_abs,
5317  library_parent_filepath(mainvar->curlib));
5318  }
5319 
5320  id->tag &= ~LIB_TAG_ID_LINK_PLACEHOLDER;
5321  id->flag &= ~LIB_INDIRECT_WEAK_LINK;
5322 
5323  if (bhead) {
5324  id->tag |= LIB_TAG_NEED_EXPAND;
5325  // printf("read lib block %s\n", id->name);
5326  read_libblock(fd, mainvar, bhead, id->tag, false, r_id);
5327  }
5328  else {
5329  BLO_reportf_wrap(basefd->reports,
5330  RPT_INFO,
5331  TIP_("LIB: %s: '%s' missing from '%s', parent '%s'"),
5333  id->name + 2,
5334  mainvar->curlib->filepath_abs,
5335  library_parent_filepath(mainvar->curlib));
5336  basefd->library_id_missing_count++;
5337 
5338  /* Generate a placeholder for this ID (simplified version of read_libblock actually...). */
5339  if (r_id) {
5340  *r_id = is_valid ? create_placeholder(mainvar, GS(id->name), id->name + 2, id->tag) : NULL;
5341  }
5342  }
5343 }
5344 
5345 static void read_library_linked_ids(FileData *basefd,
5346  FileData *fd,
5347  ListBase *mainlist,
5348  Main *mainvar)
5349 {
5350  GHash *loaded_ids = BLI_ghash_str_new(__func__);
5351 
5352  ListBase *lbarray[INDEX_ID_MAX];
5353  int a = set_listbasepointers(mainvar, lbarray);
5354 
5355  while (a--) {
5356  ID *id = lbarray[a]->first;
5357  ListBase pending_free_ids = {NULL};
5358 
5359  while (id) {
5360  ID *id_next = id->next;
5362  BLI_remlink(lbarray[a], id);
5363 
5364  /* When playing with lib renaming and such, you may end with cases where
5365  * you have more than one linked ID of the same data-block from same
5366  * library. This is absolutely horrible, hence we use a ghash to ensure
5367  * we go back to a single linked data when loading the file. */
5368  ID **realid = NULL;
5369  if (!BLI_ghash_ensure_p(loaded_ids, id->name, (void ***)&realid)) {
5370  read_library_linked_id(basefd, fd, mainvar, id, realid);
5371  }
5372 
5373  /* realid shall never be NULL - unless some source file/lib is broken
5374  * (known case: some directly linked shapekey from a missing lib...). */
5375  /* BLI_assert(*realid != NULL); */
5376 
5377  /* Now that we have a real ID, replace all pointers to placeholders in
5378  * fd->libmap with pointers to the real data-blocks. We do this for all
5379  * libraries since multiple might be referencing this ID. */
5380  change_link_placeholder_to_real_ID_pointer(mainlist, basefd, id, *realid);
5381 
5382  /* We cannot free old lib-ref placeholder ID here anymore, since we use
5383  * its name as key in loaded_ids hash. */
5384  BLI_addtail(&pending_free_ids, id);
5385  }
5386  id = id_next;
5387  }
5388 
5389  /* Clear GHash and free link placeholder IDs of the current type. */
5390  BLI_ghash_clear(loaded_ids, NULL, NULL);
5391  BLI_freelistN(&pending_free_ids);
5392  }
5393 
5394  BLI_ghash_free(loaded_ids, NULL, NULL);
5395 }
5396 
5397 static void read_library_clear_weak_links(FileData *basefd, ListBase *mainlist, Main *mainvar)
5398 {
5399  /* Any remaining weak links at this point have been lost, silently drop
5400  * those by setting them to NULL pointers. */
5401  ListBase *lbarray[INDEX_ID_MAX];
5402  int a = set_listbasepointers(mainvar, lbarray);
5403 
5404  while (a--) {
5405  ID *id = lbarray[a]->first;
5406 
5407  while (id) {
5408  ID *id_next = id->next;
5410  /* printf("Dropping weak link to %s\n", id->name); */
5411  change_link_placeholder_to_real_ID_pointer(mainlist, basefd, id, NULL);
5412  BLI_freelinkN(lbarray[a], id);
5413  }
5414  id = id_next;
5415  }
5416  }
5417 }
5418 
5420  ListBase *mainlist,
5421  Main *mainl,
5422  Main *mainptr)
5423 {
5424  FileData *fd = mainptr->curlib->filedata;
5425 
5426  if (fd != NULL) {
5427  /* File already open. */
5428  return fd;
5429  }
5430 
5431  if (mainptr->curlib->packedfile) {
5432  /* Read packed file. */
5433  PackedFile *pf = mainptr->curlib->packedfile;
5434 
5435  BLO_reportf_wrap(basefd->reports,
5436  RPT_INFO,
5437  TIP_("Read packed library: '%s', parent '%s'"),
5438  mainptr->curlib->filepath,
5439  library_parent_filepath(mainptr->curlib));
5440  fd = blo_filedata_from_memory(pf->data, pf->size, basefd->reports);
5441 
5442  /* Needed for library_append and read_libraries. */
5443  BLI_strncpy(fd->relabase, mainptr->curlib->filepath_abs, sizeof(fd->relabase));
5444  }
5445  else {
5446  /* Read file on disk. */
5447  BLO_reportf_wrap(basefd->reports,
5448  RPT_INFO,
5449  TIP_("Read library: '%s', '%s', parent '%s'"),
5450  mainptr->curlib->filepath_abs,
5451  mainptr->curlib->filepath,
5452  library_parent_filepath(mainptr->curlib));
5453  fd = blo_filedata_from_file(mainptr->curlib->filepath_abs, basefd->reports);
5454  }
5455 
5456  if (fd) {
5457  /* Share the mainlist, so all libraries are added immediately in a
5458  * single list. It used to be that all FileData's had their own list,
5459  * but with indirectly linking this meant we didn't catch duplicate
5460  * libraries properly. */
5461  fd->mainlist = mainlist;
5462 
5463  fd->reports = basefd->reports;
5464 
5465  if (fd->libmap) {
5466  oldnewmap_free(fd->libmap);
5467  }
5468 
5469  fd->libmap = oldnewmap_new();
5470 
5471  mainptr->curlib->filedata = fd;
5472  mainptr->versionfile = fd->fileversion;
5473 
5474  /* subversion */
5475  read_file_version(fd, mainptr);
5476 #ifdef USE_GHASH_BHEAD
5478 #endif
5479  }
5480  else {
5481  mainptr->curlib->filedata = NULL;
5482  mainptr->curlib->id.tag |= LIB_TAG_MISSING;
5483  /* Set lib version to current main one... Makes assert later happy. */
5484  mainptr->versionfile = mainptr->curlib->versionfile = mainl->versionfile;
5485  mainptr->subversionfile = mainptr->curlib->subversionfile = mainl->subversionfile;
5486  }
5487 
5488  if (fd == NULL) {
5490  basefd->reports, RPT_INFO, TIP_("Cannot find lib '%s'"), mainptr->curlib->filepath_abs);
5491  basefd->library_file_missing_count++;
5492  }
5493 
5494  return fd;
5495 }
5496 
5497 static void read_libraries(FileData *basefd, ListBase *mainlist)
5498 {
5499  Main *mainl = mainlist->first;
5500  bool do_it = true;
5501 
5502  /* Expander is now callback function. */
5504 
5505  /* At this point the base blend file has been read, and each library blend
5506  * encountered so far has a main with placeholders for linked data-blocks.
5507  *
5508  * Now we will read the library blend files and replace the placeholders
5509  * with actual data-blocks. We loop over library mains multiple times in
5510  * case a library needs to link additional data-blocks from another library
5511  * that had been read previously. */
5512  while (do_it) {
5513  do_it = false;
5514 
5515  /* Loop over mains of all library blend files encountered so far. Note
5516  * this list gets longer as more indirectly library blends are found. */
5517  for (Main *mainptr = mainl->next; mainptr; mainptr = mainptr->next) {
5518  /* Does this library have any more linked data-blocks we need to read? */
5519  if (has_linked_ids_to_read(mainptr)) {
5520 #if 0
5521  printf("Reading linked data-blocks from %s (%s)\n",
5522  mainptr->curlib->id.name,
5523  mainptr->curlib->filepath);
5524 #endif
5525 
5526  /* Open file if it has not been done yet. */
5527  FileData *fd = read_library_file_data(basefd, mainlist, mainl, mainptr);
5528 
5529  if (fd) {
5530  do_it = true;
5531  }
5532 
5533  /* Read linked data-locks for each link placeholder, and replace
5534  * the placeholder with the real data-lock. */
5535  read_library_linked_ids(basefd, fd, mainlist, mainptr);
5536 
5537  /* Test if linked data-locks need to read further linked data-locks
5538  * and create link placeholders for them. */
5539  BLO_expand_main(fd, mainptr);
5540  }
5541  }
5542  }
5543 
5544  for (Main *mainptr = mainl->next; mainptr; mainptr = mainptr->next) {
5545  /* Drop weak links for which no data-block was found.
5546  * Since this can remap pointers in `libmap` of all libraries, it needs to be performed in its
5547  * own loop, before any call to `lib_link_all` (and the freeing of the libraries' filedata). */
5548  read_library_clear_weak_links(basefd, mainlist, mainptr);
5549  }
5550 
5551  Main *main_newid = BKE_main_new();
5552  for (Main *mainptr = mainl->next; mainptr; mainptr = mainptr->next) {
5553  /* Do versioning for newly added linked data-locks. If no data-locks
5554  * were read from a library versionfile will still be zero and we can
5555  * skip it. */
5556  if (mainptr->versionfile) {
5557  /* Split out already existing IDs to avoid them going through
5558  * do_versions multiple times, which would have bad consequences. */
5559  split_main_newid(mainptr, main_newid);
5560 
5561  /* File data can be zero with link/append. */
5562  if (mainptr->curlib->filedata) {
5563  do_versions(mainptr->curlib->filedata, mainptr->curlib, main_newid);
5564  }
5565  else {
5566  do_versions(basefd, NULL, main_newid);
5567  }
5568 
5569  add_main_to_main(mainptr, main_newid);
5570  }
5571 
5572  /* Lib linking. */
5573  if (mainptr->curlib->filedata) {
5574  lib_link_all(mainptr->curlib->filedata, mainptr);
5575  }
5576 
5577  /* Note: No need to call #do_versions_after_linking() or #BKE_main_id_refcount_recompute()
5578  * here, as this function is only called for library 'subset' data handling, as part of
5579  * either full blendfile reading (#blo_read_file_internal()), or library-data linking
5580  * (#library_link_end()). */
5581 
5582  /* Free file data we no longer need. */
5583  if (mainptr->curlib->filedata) {
5584  blo_filedata_free(mainptr->curlib->filedata);
5585  }
5586  mainptr->curlib->filedata = NULL;
5587  }
5588  BKE_main_free(main_newid);
5589 
5590  if (basefd->library_file_missing_count != 0 || basefd->library_id_missing_count != 0) {
5591  BKE_reportf(basefd->reports,
5592  RPT_WARNING,
5593  "LIB: %d libraries and %d linked data-blocks are missing, please check the "
5594  "Info and Outliner editors for details",
5596  basefd->library_id_missing_count);
5597  }
5598 }
5599 
5600 void *BLO_read_get_new_data_address(BlendDataReader *reader, const void *old_address)
5601 {
5602  return newdataadr(reader->fd, old_address);
5603 }
5604 
5605 void *BLO_read_get_new_data_address_no_us(BlendDataReader *reader, const void *old_address)
5606 {
5607  return newdataadr_no_us(reader->fd, old_address);
5608 }
5609 
5610 void *BLO_read_get_new_packed_address(BlendDataReader *reader, const void *old_address)
5611 {
5612  return newpackedadr(reader->fd, old_address);
5613 }
5614 
5616 {
5617  return newlibadr(reader->fd, lib, id);
5618 }
5619 
5621 {
5622  return (reader->fd->flags & FD_FLAGS_SWITCH_ENDIAN) != 0;
5623 }
5624 
5631 {
5632  if (BLI_listbase_is_empty(list)) {
5633  return;
5634  }
5635 
5636  BLO_read_data_address(reader, &list->first);
5637  if (callback != NULL) {
5638  callback(reader, list->first);
5639  }
5640  Link *ln = list->first;
5641  Link *prev = NULL;
5642  while (ln) {
5643  BLO_read_data_address(reader, &ln->next);
5644  if (ln->next != NULL && callback != NULL) {
5645  callback(reader, ln->next);
5646  }
5647  ln->prev = prev;
5648  prev = ln;
5649  ln = ln->next;
5650  }
5651  list->last = prev;
5652 }
5653 
5654 void BLO_read_list(BlendDataReader *reader, struct ListBase *list)
5655 {
5656  BLO_read_list_cb(reader, list, NULL);
5657 }
5658 
5659 void BLO_read_int32_array(BlendDataReader *reader, int array_size, int32_t **ptr_p)
5660 {
5661  BLO_read_data_address(reader, ptr_p);
5662  if (BLO_read_requires_endian_switch(reader)) {
5663  BLI_endian_switch_int32_array(*ptr_p, array_size);
5664  }
5665 }
5666 
5667 void BLO_read_uint32_array(BlendDataReader *reader, int array_size, uint32_t **ptr_p)
5668 {
5669  BLO_read_data_address(reader, ptr_p);
5670  if (BLO_read_requires_endian_switch(reader)) {
5671  BLI_endian_switch_uint32_array(*ptr_p, array_size);
5672  }
5673 }
5674 
5675 void BLO_read_float_array(BlendDataReader *reader, int array_size, float **ptr_p)
5676 {
5677  BLO_read_data_address(reader, ptr_p);
5678  if (BLO_read_requires_endian_switch(reader)) {
5679  BLI_endian_switch_float_array(*ptr_p, array_size);
5680  }
5681 }
5682 
5683 void BLO_read_float3_array(BlendDataReader *reader, int array_size, float **ptr_p)
5684 {
5685  BLO_read_float_array(reader, array_size * 3, ptr_p);
5686 }
5687 
5688 void BLO_read_double_array(BlendDataReader *reader, int array_size, double **ptr_p)
5689 {
5690  BLO_read_data_address(reader, ptr_p);
5691  if (BLO_read_requires_endian_switch(reader)) {
5692  BLI_endian_switch_double_array(*ptr_p, array_size);
5693  }
5694 }
5695 
5697  uint array_size,
5698  const uint64_t *src,
5699  uint32_t *dst)
5700 {
5701  /* Match pointer conversion rules from bh4_from_bh8 and cast_pointer. */
5702  if (BLO_read_requires_endian_switch(reader)) {
5703  for (int i = 0; i < array_size; i++) {
5704  uint64_t ptr = src[i];
5706  dst[i] = (uint32_t)(ptr >> 3);
5707  }
5708  }
5709  else {
5710  for (int i = 0; i < array_size; i++) {
5711  dst[i] = (uint32_t)(src[i] >> 3);
5712  }
5713  }
5714 }
5715 
5717  uint array_size,
5718  const uint32_t *src,
5719  uint64_t *dst)
5720 {
5721  /* Match pointer conversion rules from bh8_from_bh4 and cast_pointer_32_to_64. */
5722  for (int i = 0; i < array_size; i++) {
5723  dst[i] = src[i];
5724  }
5725 }
5726 
5727 void BLO_read_pointer_array(BlendDataReader *reader, void **ptr_p)
5728 {
5729  FileData *fd = reader->fd;
5730 
5731  void *orig_array = newdataadr(fd, *ptr_p);
5732  if (orig_array == NULL) {
5733  *ptr_p = NULL;
5734  return;
5735  }
5736 
5737  int file_pointer_size = fd->filesdna->pointer_size;
5738  int current_pointer_size = fd->memsdna->pointer_size;
5739 
5740  /* Over-allocation is fine, but might be better to pass the length as parameter. */
5741  int array_size = MEM_allocN_len(orig_array) / file_pointer_size;
5742 
5743  void *final_array = NULL;
5744 
5745  if (file_pointer_size == current_pointer_size) {
5746  /* No pointer conversion necessary. */
5747  final_array = orig_array;
5748  }
5749  else if (file_pointer_size == 8 && current_pointer_size == 4) {
5750  /* Convert pointers from 64 to 32 bit. */
5751  final_array = MEM_malloc_arrayN(array_size, 4, "new pointer array");
5753  reader, array_size, (uint64_t *)orig_array, (uint32_t *)final_array);
5754  MEM_freeN(orig_array);
5755  }
5756  else if (file_pointer_size == 4 && current_pointer_size == 8) {
5757  /* Convert pointers from 32 to 64 bit. */
5758  final_array = MEM_malloc_arrayN(array_size, 8, "new pointer array");
5760  reader, array_size, (uint32_t *)orig_array, (uint64_t *)final_array);
5761  MEM_freeN(orig_array);
5762  }
5763  else {
5764  BLI_assert(false);
5765  }
5766 
5767  *ptr_p = final_array;
5768 }
5769 
5771 {
5772  return reader->fd->memfile != NULL;
5773 }
5774 
5775 void BLO_read_data_globmap_add(BlendDataReader *reader, void *oldaddr, void *newaddr)
5776 {
5777  oldnewmap_insert(reader->fd->globmap, oldaddr, newaddr, 0);
5778 }
5779 
5781 {
5782  link_glob_list(reader->fd, list);
5783 }
5784 
5786 {
5787  return reader->fd->reports;
5788 }
5789 
5791 {
5792  return reader->fd->memfile != NULL;
5793 }
5794 
5796 {
5797  return reader->main;
5798 }
5799 
5801 {
5802  return reader->fd->reports;
5803 }
5804 
5805 void BLO_expand_id(BlendExpander *expander, ID *id)
5806 {
5807  expand_doit(expander->fd, expander->main, id);
5808 }
5809 
void BKE_animdata_blend_read_lib(struct BlendLibReader *reader, struct ID *id, struct AnimData *adt)
Definition: anim_data.c:1603
void BKE_animdata_blend_read_expand(struct BlendExpander *expander, struct AnimData *adt)
Definition: anim_data.c:1622
struct AnimData * BKE_animdata_from_id(struct ID *id)
Definition: anim_data.c:96
void BKE_asset_metadata_read(struct BlendDataReader *reader, struct AssetMetaData *asset_data)
Definition: asset.cc:139
struct Collection * BKE_collection_add(struct Main *bmain, struct Collection *parent, const char *name)
Definition: collection.c:435
bool BKE_collection_child_add(struct Main *bmain, struct Collection *parent, struct Collection *child)
Definition: collection.c:1606
bool BKE_collection_object_add(struct Main *bmain, struct Collection *collection, struct Object *ob)
Definition: collection.c:1134
void BKE_collection_blend_read_data(struct BlendDataReader *reader, struct Collection *collection)
Definition: collection.c:244
void BKE_collection_blend_read_lib(struct BlendLibReader *reader, struct Collection *collection)
Definition: collection.c:310
bool BKE_collection_has_object(struct Collection *collection, const struct Object *ob)
void BKE_collection_blend_read_expand(struct BlendExpander *expander, struct Collection *collection)
Definition: collection.c:345
void BKE_collections_after_lib_link(struct Main *bmain)
Definition: collection.c:1406
void BKE_main_collections_parent_relations_rebuild(struct Main *bmain)
Definition: collection.c:1671
@ G_FILE_RECOVER_READ
Definition: BKE_global.h:182
#define B_ENDIAN
Definition: BKE_global.h:208
#define L_ENDIAN
Definition: BKE_global.h:207
@ G_DEBUG
Definition: BKE_global.h:133
#define ENDIAN_ORDER
Definition: BKE_global.h:213
void IDP_BlendReadExpand(struct BlendExpander *expander, struct IDProperty *prop)
Definition: idprop.c:1336
void IDP_BlendReadLib(struct BlendLibReader *reader, struct IDProperty *prop)
Definition: idprop.c:1300
#define IDP_BlendDataRead(reader, prop)
Definition: BKE_idprop.h:208
bool BKE_idtype_cache_key_cmp(const void *key_a_v, const void *key_b_v)
Definition: idtype.c:58
short BKE_idtype_idcode_from_index(const int index)
Definition: idtype.c:407
bool BKE_idtype_idcode_is_linkable(const short idcode)
Definition: idtype.c:232
bool BKE_idtype_idcode_is_valid(const short idcode)
Definition: idtype.c:221
void BKE_idtype_id_foreach_cache(struct ID *id, IDTypeForeachCacheFunctionCallback function_callback, void *user_data)
Definition: idtype.c:480
const char * BKE_idtype_idcode_to_name(const short idcode)
Definition: idtype.c:168
const struct IDTypeInfo * BKE_idtype_get_info_from_id(const struct ID *id)
uint BKE_idtype_cache_key_hash(const void *key_v)
Definition: idtype.c:50
uint64_t BKE_idtype_idcode_to_idfilter(const short idcode)
Definition: idtype.c:242
@ IDTYPE_CACHE_CB_FLAGS_PERSISTENT
Definition: BKE_idtype.h:87
struct LayerCollection * BKE_layer_collection_get_active(struct ViewLayer *view_layer)
Definition: layer.c:630
struct Base * BKE_view_layer_base_find(struct ViewLayer *view_layer, struct Object *ob)
Definition: layer.c:394
struct ViewLayer * BKE_view_layer_find(const struct Scene *scene, const char *layer_name)
void BKE_lib_libblock_session_uuid_ensure(struct ID *id)
Definition: lib_id.c:1145
void BKE_main_id_tag_all(struct Main *mainvar, const int tag, const bool value)
Definition: lib_id.c:923
void * BKE_libblock_alloc(struct Main *bmain, short type, const char *name, const int flag) ATTR_WARN_UNUSED_RESULT
Definition: lib_id.c:1062
void * BKE_libblock_alloc_notest(short type) ATTR_WARN_UNUSED_RESULT
Definition: lib_id.c:1045
void BKE_lib_id_swap_full(struct Main *bmain, struct ID *id_a, struct ID *id_b)
Definition: lib_id.c:741
void BKE_id_free(struct Main *bmain, void *idv)
void BKE_libblock_init_empty(struct ID *id) ATTR_NONNULL(1)
Definition: lib_id.c:1122
void id_us_ensure_real(struct ID *id)
Definition: lib_id.c:238
void id_us_plus(struct ID *id)
Definition: lib_id.c:288
void BKE_main_id_tag_idcode(struct Main *mainvar, const short type, const int tag, const bool value)
Definition: lib_id.c:910
struct ID * BKE_libblock_find_name(struct Main *bmain, const short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: lib_id.c:1333
#define MAIN_ID_SESSION_UUID_UNSET
Definition: BKE_lib_id.h:73
void BKE_main_id_refcount_recompute(struct Main *bmain, const bool do_linked_only)
Definition: lib_id.c:1773
void id_sort_by_name(struct ListBase *lb, struct ID *id, struct ID *id_sorting_hint)
Definition: lib_id.c:1348
void BKE_lib_override_library_main_update(struct Main *bmain)
void BKE_lib_override_library_main_validate(struct Main *bmain, struct ReportList *reports)
@ IDWALK_NOP
void BKE_library_foreach_ID_link(struct Main *bmain, struct ID *id, LibraryIDLinkCallback callback, void *user_data, int flag)
Definition: lib_query.c:322
@ IDWALK_RET_NOP
Definition: BKE_lib_query.h:97
@ IDWALK_CB_USER_ONE
Definition: BKE_lib_query.h:93
@ IDWALK_CB_EMBEDDED
Definition: BKE_lib_query.h:62
#define FOREACH_MAIN_ID_END
Definition: BKE_main.h:250
struct Main * BKE_main_new(void)
Definition: main.c:45
#define FOREACH_MAIN_LISTBASE_ID_END
Definition: BKE_main.h:219
int set_listbasepointers(struct Main *main, struct ListBase *lb[])
#define FOREACH_MAIN_LISTBASE_ID_BEGIN(_lb, _id)
Definition: BKE_main.h:213
#define FOREACH_MAIN_LISTBASE_END
Definition: BKE_main.h:231
const char * BKE_main_blendfile_path(const struct Main *bmain) ATTR_NONNULL()
#define FOREACH_MAIN_LISTBASE_BEGIN(_bmain, _lb)
Definition: BKE_main.h:224
#define FOREACH_MAIN_ID_BEGIN(_bmain, _id)
Definition: BKE_main.h:244
#define BLEN_THUMB_MEMSIZE(_x, _y)
Definition: BKE_main.h:279
struct ListBase * which_libbase(struct Main *bmain, short type)
Definition: main.c:447
#define BLEN_THUMB_MEMSIZE_IS_VALID(_x, _y)
Definition: BKE_main.h:282
void BKE_main_free(struct Main *mainvar)
Definition: main.c:53
const char * BKE_main_blendfile_path_from_global(void)
Definition: main.c:439
struct IDNameLib_Map * BKE_main_idmap_create(struct Main *bmain, const bool create_valid_ids_set, struct Main *old_bmain, const int idmap_types) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition: main_idmap.c:101
struct ID struct ID struct ID * BKE_main_idmap_lookup_uuid(struct IDNameLib_Map *id_map, const uint session_uuid) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition: main_idmap.c:222
void BKE_main_idmap_destroy(struct IDNameLib_Map *id_map) ATTR_NONNULL()
Definition: main_idmap.c:230
struct Main * BKE_main_idmap_main_get(struct IDNameLib_Map *id_map) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: main_idmap.c:151
struct ID struct ID * BKE_main_idmap_lookup_id(struct IDNameLib_Map *id_map, const struct ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
@ MAIN_IDMAP_TYPE_UUID
@ MAIN_IDMAP_TYPE_NAME
General operations, lookup, etc. for materials.
void BKE_object_materials_test(struct Main *bmain, struct Object *ob, struct ID *id)
Definition: material.c:772
struct bNodeTree * ntreeFromID(struct ID *id)
Definition: node.cc:3147
void ntreeBlendReadData(struct BlendDataReader *reader, struct bNodeTree *ntree)
Definition: node.cc:626
void ntreeBlendReadLib(struct BlendLibReader *reader, struct bNodeTree *ntree)
Definition: node.cc:828
struct bNodeTree ** BKE_ntree_ptr_from_id(struct ID *id)
Definition: node.cc:3124
void ntreeBlendReadExpand(struct BlendExpander *expander, struct bNodeTree *ntree)
Definition: node.cc:914
void ntreeUpdateAllNew(struct Main *main)
Definition: node.cc:4200
General operations, lookup, etc. for blender objects.
struct Object * BKE_object_add_only_object(struct Main *bmain, int type, const char *name) ATTR_NONNULL(1) ATTR_RETURNS_NONNULL
Definition: object.c:2193
int BKE_object_obdata_to_type(const struct ID *id) ATTR_NONNULL(1)
void BKE_packedfile_blend_read(struct BlendDataReader *reader, struct PackedFile **pf_p)
Definition: packedFile.c:885
void BKE_report(ReportList *reports, ReportType type, const char *message)
Definition: report.c:104
const char * BKE_report_type_str(ReportType type)
Definition: report.c:40
void BKE_reportf(ReportList *reports, ReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
bool BKE_scene_object_find(struct Scene *scene, struct Object *ob)
Definition: scene.c:2092
void BKE_scene_object_base_flag_sync_from_base(struct Base *base)
Definition: scene.c:2966
bool BKE_screen_blend_read_data(struct BlendDataReader *reader, struct bScreen *screen)
Definition: screen.c:273
@ STEP_UNDO
@ STEP_REDO
struct WorkSpace * BKE_workspace_active_get(struct WorkSpaceInstanceHook *hook) GETTER_ATTRS
Definition: workspace.c:535
struct bScreen * BKE_workspace_active_screen_get(const struct WorkSpaceInstanceHook *hook) GETTER_ATTRS
void BKE_workspace_active_set(struct WorkSpaceInstanceHook *hook, struct WorkSpace *workspace) SETTER_ATTRS
Definition: workspace.c:539
struct bScreen * BKE_workspace_layout_screen_get(const struct WorkSpaceLayout *layout) GETTER_ATTRS
#define BLI_STATIC_ASSERT(a, msg)
Definition: BLI_assert.h:86
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define ATTR_FALLTHROUGH
BLI_INLINE void BLI_endian_switch_uint64(uint64_t *val) ATTR_NONNULL(1)
void BLI_endian_switch_double_array(double *val, const int size) ATTR_NONNULL(1)
Definition: endian_switch.c:95
void BLI_endian_switch_int32_array(int *val, const int size) ATTR_NONNULL(1)
Definition: endian_switch.c:45
void BLI_endian_switch_uint32_array(unsigned int *val, const int size) ATTR_NONNULL(1)
Definition: endian_switch.c:55
void BLI_endian_switch_float_array(float *val, const int size) ATTR_NONNULL(1)
Definition: endian_switch.c:65
BLI_INLINE void BLI_endian_switch_int32(int *val) ATTR_NONNULL(1)
int BLI_open(const char *filename, int oflag, int pmode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: fileops.c:1017
#define O_BINARY
Definition: BLI_fileops.h:182
bool BLI_is_file(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: storage.c:444
int64_t BLI_lseek(int fd, int64_t offset, int whence)
Definition: storage.c:195
bool BLI_is_dir(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: storage.c:436
void * BLI_gzopen(const char *filename, const char *mode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: fileops.c:1010
void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:996
GHash * BLI_ghash_str_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
GHash * BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:718
bool BLI_ghash_haskey(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:941
GHash * BLI_ghash_str_new_ex(const char *info, const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition: BLI_ghash.c:756
void ** BLI_ghash_lookup_p(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:830
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:1008
bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:851
void * BLI_ghash_lookup(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:803
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:124
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:281
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
Definition: BLI_listbase.h:188
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
Definition: BLI_listbase.h:128
void void void BLI_movelisttolist(struct ListBase *dst, struct ListBase *src) ATTR_NONNULL(1
bool BLI_remlink_safe(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:159
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:547
void * BLI_findstring(const struct ListBase *listbase, const char *id, const int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:133
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE void copy_v3_v3(float r[3], const float a[3])
void BLI_memarena_free(struct MemArena *ma) ATTR_NONNULL(1)
Definition: BLI_memarena.c:109
#define BLI_MEMARENA_STD_BUFSIZE
Definition: BLI_memarena.h:36
void * BLI_memarena_alloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
Definition: BLI_memarena.c:131
struct MemArena * BLI_memarena_new(const size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2) ATTR_MALLOC
Definition: BLI_memarena.c:79
void BLI_mempool_iternew(BLI_mempool *pool, BLI_mempool_iter *iter) ATTR_NONNULL()
Definition: BLI_mempool.c:537
void * BLI_mempool_iterstep(BLI_mempool_iter *iter) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: BLI_mempool.c:645
bool BLI_mmap_read(BLI_mmap_file *file, void *dest, size_t offset, size_t length) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition: BLI_mmap.c:194
BLI_mmap_file * BLI_mmap_open(int fd) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_mmap.c:147
void BLI_mmap_free(BLI_mmap_file *file) ATTR_NONNULL(1)
Definition: BLI_mmap.c:226
bool BLI_path_extension_check_array(const char *str, const char **ext_array) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
Definition: path_util.c:1487
const char * BLI_path_basename(const char *path) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
Definition: path_util.c:1868
bool BLI_path_is_rel(const char *path) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
Definition: path_util.c:411
#define FILE_MAX
void BLI_path_normalize(const char *relabase, char *path) ATTR_NONNULL(2)
Definition: path_util.c:173
void BLI_path_rel(char *file, const char *relfile) ATTR_NONNULL()
Definition: path_util.c:519
const char * BLI_path_slash_rfind(const char *string) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
Definition: path_util.c:1962
#define BLI_path_cmp
#define STRNCPY(dst, src)
Definition: BLI_string.h:163
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
unsigned int uint
Definition: BLI_sys_types.h:83
#define UNUSED_VARS(...)
#define STREQLEN(a, b, n)
#define POINTER_AS_UINT(i)
#define UNUSED_VARS_NDEBUG(...)
#define UNUSED(x)
#define UNLIKELY(x)
#define ELEM(...)
#define MIN2(a, b)
#define POINTER_FROM_UINT(i)
#define POINTER_OFFSET(v, ofs)
#define STREQ(a, b)
#define CLAMP_MIN(a, b)
#define LIKELY(x)
Compatibility-like things for windows.
SSIZE_T ssize_t
Definition: BLI_winstuff.h:87
defines for blend-file codes.
@ GLOB
@ DNA1
@ ENDB
@ DATA
@ TEST
@ USER
@ REND
#define BLEN_THUMB_MEMSIZE_FILE(_x, _y)
Utils ensuring .blend file (i.e. Main) is in valid state during write and/or read process.
bool BLO_main_validate_shapekeys(struct Main *bmain, struct ReportList *reports)
#define BLO_read_data_address(reader, ptr_p)
void(* BlendReadListFn)(BlendDataReader *reader, void *data)
#define BLO_read_id_address(reader, lib, id_ptr_p)
#define BLO_expand(expander, id)
external readfile function prototypes.
void(* BLOExpandDoitCallback)(void *fdhandle, struct Main *mainvar, void *idv)
Definition: BLO_readfile.h:259
@ BLO_LIBLINK_USE_PLACEHOLDERS
Definition: BLO_readfile.h:163
@ BLO_LIBLINK_NEEDS_ID_TAG_DOIT
Definition: BLO_readfile.h:173
@ BLO_LIBLINK_FORCE_INDIRECT
Definition: BLO_readfile.h:165
#define BLO_GROUP_MAX
Definition: BLO_readfile.h:146
@ BLO_READ_SKIP_DATA
Definition: BLO_readfile.h:96
@ BLO_READ_SKIP_USERDEF
Definition: BLO_readfile.h:95
@ BLO_READ_SKIP_UNDO_OLD_MAIN
Definition: BLO_readfile.h:98
struct BlendHandle BlendHandle
Definition: BLO_readfile.h:49
#define BLO_EMBEDDED_STARTUP_BLEND
Definition: BLO_readfile.h:147
@ BLENFILETYPE_BLEND
Definition: BLO_readfile.h:64
#define TIP_(msgid)
void DEG_id_tag_update(struct ID *id, int flag)
#define ID_FAKE_USERS(id)
Definition: DNA_ID.h:412
@ ID_RECALC_TRANSFORM
Definition: DNA_ID.h:599
@ ID_RECALC_COPY_ON_WRITE
Definition: DNA_ID.h:654
@ ID_RECALC_ANIMATION
Definition: DNA_ID.h:614
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:611
@ ID_RECALC_ALL
Definition: DNA_ID.h:697
@ LIB_TAG_INDIRECT
Definition: DNA_ID.h:524
@ LIB_TAG_EXTRAUSER
Definition: DNA_ID.h:545
@ LIB_TAG_TEMP_MAIN
Definition: DNA_ID.h:585
@ LIB_TAG_NEW
Definition: DNA_ID.h:551
@ LIB_TAG_PRE_EXISTING
Definition: DNA_ID.h:556
@ LIB_TAG_UNDO_OLD_ID_REUSED
Definition: DNA_ID.h:580
@ LIB_TAG_LOCAL
Definition: DNA_ID.h:518
@ LIB_TAG_DOIT
Definition: DNA_ID.h:554
@ LIB_TAG_NEED_EXPAND
Definition: DNA_ID.h:528
@ LIB_TAG_EXTERN
Definition: DNA_ID.h:521
@ LIB_TAG_MISSING
Definition: DNA_ID.h:537
@ LIB_TAG_NEED_LINK
Definition: DNA_ID.h:533
@ LIB_TAG_ID_LINK_PLACEHOLDER
Definition: DNA_ID.h:531
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:426
#define MAX_ID_NAME
Definition: DNA_ID.h:269
@ LIB_INDIRECT_WEAK_LINK
Definition: DNA_ID.h:488
@ INDEX_ID_MAX
Definition: DNA_ID.h:859
ID_Type
Definition: DNA_ID_enums.h:56
@ ID_WM
Definition: DNA_ID_enums.h:84
@ ID_CA
Definition: DNA_ID_enums.h:68
@ ID_AR
Definition: DNA_ID_enums.h:78
@ ID_MC
Definition: DNA_ID_enums.h:85
@ ID_CF
Definition: DNA_ID_enums.h:90
@ ID_LI
Definition: DNA_ID_enums.h:58
@ ID_TE
Definition: DNA_ID_enums.h:64
@ ID_IM
Definition: DNA_ID_enums.h:65
@ ID_VO
Definition: DNA_ID_enums.h:95
@ ID_WS
Definition: DNA_ID_enums.h:91
@ ID_NT
Definition: DNA_ID_enums.h:80
@ ID_LA
Definition: DNA_ID_enums.h:67
@ ID_KE
Definition: DNA_ID_enums.h:70
@ ID_TXT
Definition: DNA_ID_enums.h:74
@ ID_SO
Definition: DNA_ID_enums.h:76
@ ID_SCE
Definition: DNA_ID_enums.h:57
@ ID_LS
Definition: DNA_ID_enums.h:87
@ ID_MSK
Definition: DNA_ID_enums.h:86
@ ID_GD
Definition: DNA_ID_enums.h:83
@ ID_PAL
Definition: DNA_ID_enums.h:88
@ ID_BR
Definition: DNA_ID_enums.h:81
@ ID_LP
Definition: DNA_ID_enums.h:92
@ ID_HA
Definition: DNA_ID_enums.h:93
@ ID_WO
Definition: DNA_ID_enums.h:71
@ ID_SIM
Definition: DNA_ID_enums.h:96
@ ID_MA
Definition: DNA_ID_enums.h:63
@ ID_AC
Definition: DNA_ID_enums.h:79
@ ID_SCR
Definition: DNA_ID_enums.h:72
@ ID_VF
Definition: DNA_ID_enums.h:73
@ ID_ME
Definition: DNA_ID_enums.h:60
@ ID_IP
Definition: DNA_ID_enums.h:69
@ ID_GR
Definition: DNA_ID_enums.h:77
@ ID_SPK
Definition: DNA_ID_enums.h:75
@ ID_MB
Definition: DNA_ID_enums.h:62
@ ID_LT
Definition: DNA_ID_enums.h:66
@ ID_OB
Definition: DNA_ID_enums.h:59
@ ID_PA
Definition: DNA_ID_enums.h:82
@ ID_PT
Definition: DNA_ID_enums.h:94
@ ID_CU
Definition: DNA_ID_enums.h:61
@ ID_PC
Definition: DNA_ID_enums.h:89
#define ID_SCRN
Definition: DNA_ID_enums.h:103
#define ID_LINK_PLACEHOLDER
Definition: DNA_ID_enums.h:100
@ SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC
Object groups, one object can be in many groups at once.
@ COLLECTION_IS_MASTER
blenloader genfile private function prototypes
void DNA_sdna_free(struct SDNA *sdna)
Definition: dna_genfile.c:139
struct SDNA * DNA_sdna_from_data(const void *data, const int data_len, bool do_endian_swap, bool data_alloc, const char **r_error_message)
Definition: dna_genfile.c:550
struct DNA_ReconstructInfo * DNA_reconstruct_info_create(const struct SDNA *oldsdna, const struct SDNA *newsdna, const char *compare_flags)
void DNA_struct_switch_endian(const struct SDNA *sdna, int struct_nr, char *data)
void * DNA_struct_reconstruct(const struct DNA_ReconstructInfo *reconstruct_info, int old_struct_nr, int blocks, const void *old_blocks)
const char * DNA_struct_get_compareflags(const struct SDNA *sdna, const struct SDNA *newsdna)
void DNA_reconstruct_info_free(struct DNA_ReconstructInfo *reconstruct_info)
Definition: dna_genfile.c:1612
const struct SDNA * DNA_sdna_current_get(void)
Definition: dna_genfile.c:597
int DNA_elem_offset(struct SDNA *sdna, const char *stype, const char *vartype, const char *name)
Definition: dna_genfile.c:1628
@ SDNA_CMP_REMOVED
Definition: DNA_genfile.h:75
@ SDNA_CMP_NOT_EQUAL
Definition: DNA_genfile.h:81
@ BASE_SELECTABLE
@ BASE_SELECTED
@ OB_MODE_EDIT
@ OB_MODE_OBJECT
#define OB_DATA_SUPPORT_ID(_id_type)
@ OB_DUPLICOLLECTION
@ OB_EMPTY
#define TSE_IS_REAL_ID(_tse)
#define SCE_READFILE_LIBLINK_NEED_SETSCENE_CHECK
@ RGN_TYPE_WINDOW
@ SPREADSHEET_CONTEXT_OBJECT
@ SPACE_TEXT
@ SPACE_CLIP
@ SPACE_ACTION
@ SPACE_OUTLINER
@ SPACE_NODE
@ SPACE_SPREADSHEET
@ SPACE_FILE
@ SPACE_PROPERTIES
@ SPACE_NLA
@ SPACE_SEQ
@ SPACE_SCRIPT
@ SPACE_IMAGE
@ SPACE_GRAPH
@ SPACE_VIEW3D
#define SCRIPT_SET_NULL(_script)
@ FILE_TAG_REBUILD_MAIN_FILES
@ SB_PIN_CONTEXT
@ SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC_COLOR
@ SO_TREESTORE_REBUILD
@ FILE_ACTIVE_COLLECTION
@ FILE_RELPATH
@ FILE_AUTOSELECT
@ FILE_OBDATA_INSTANCE
@ FILE_LINK
@ FILE_COLLECTION_INSTANCE
@ USER_MENU_TYPE_OPERATOR
struct DrawDataList * DRW_drawdatalist_from_id(struct ID *id)
Definition: draw_manager.c:869
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble x2
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define MEM_reallocN(vmemh, len)
ATTR_WARN_UNUSED_RESULT const BMVert * v2
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
unsigned int U
Definition: btGjkEpa3.h:78
Scene * scene
ListBase seqbase_clipboard
Definition: clipboard.c:56
StackEntry * from
FILE * file
Scene scene
bool is_valid
DEGForeachIDComponentCallback callback
bNodeTree * ntree
DRWShaderLibrary * lib
#define str(s)
static FT_Error err
Definition: freetypefont.c:52
#define pf(_x, _i)
Prefetch 64.
Definition: gim_memory.h:48
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
#define GS(x)
Definition: iris.c:241
int SEQ_iterator_seqbase_recursive_apply(ListBase *seqbase, int(*apply_fn)(Sequence *seq, void *), void *arg)
Definition: iterator.c:142
__kernel void ccl_constant KernelData ccl_global void ccl_global char ccl_global int ccl_global char ccl_global unsigned int ccl_global float * buffer
format
Definition: logImageCore.h:47
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:48
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
size_t(* MEM_allocN_len)(const void *vmemh)
Definition: mallocn.c:40
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
int main(int argc, char **argv)
Definition: msgfmt.c:457
static unsigned c
Definition: RandGen.cpp:97
static unsigned a[3]
Definition: RandGen.cpp:92
static void area(int d1, int d2, int e1, int e2, float weights[2])
void blo_do_versions_oldnewmap_insert(OldNewMap *onm, const void *oldaddr, void *newaddr, int nr)
Definition: readfile.c:380
void BLO_read_float3_array(BlendDataReader *reader, int array_size, float **ptr_p)
Definition: readfile.c:5683
void BLO_expand_main(void *fdhandle, Main *mainvar)
Definition: readfile.c:4587
static void add_loose_objects_to_scene(Main *mainvar, Main *bmain, Scene *scene, ViewLayer *view_layer, const View3D *v3d, Library *lib, const short flag)
Definition: readfile.c:4681
static void read_libraries(FileData *basefd, ListBase *mainlist)
Definition: readfile.c:5497
void BLO_reportf_wrap(ReportList *reports, ReportType type, const char *format,...)
Definition: readfile.c:228
static BHead * read_libblock(FileData *fd, Main *main, BHead *bhead, const int tag, const bool placeholder_set_indirect_extern, ID **r_id)
Definition: readfile.c:3631
void blo_make_packed_pointer_map(FileData *fd, Main *oldmain)
Definition: readfile.c:1905
static ssize_t fd_read_from_mmap(FileData *filedata, void *buffer, size_t size, bool *UNUSED(r_is_memchunck_identical))
Definition: readfile.c:1209
static void lib_link_scenes_check_set(Main *bmain)
Definition: readfile.c:2579
struct BlendLibReader BlendLibReader
static void link_glob_list(FileData *fd, ListBase *lb)
Definition: readfile.c:2250
static void bh8_from_bh4(BHead *bhead, BHead4 *bhead4)
Definition: readfile.c:742
static BHead * blo_bhead_read_full(FileData *fd, BHead *thisblock)
Definition: readfile.c:970
static void lib_link_all(FileData *fd, Main *bmain)
Definition: readfile.c:3905
void blo_cache_storage_end(FileData *fd)
Definition: readfile.c:2141
static void convert_pointer_array_32_to_64(BlendDataReader *UNUSED(reader), uint array_size, const uint32_t *src, uint64_t *dst)
Definition: readfile.c:5716
static void restore_pointer_user(ID *id, ID *newid, ePointerUserMode user)
Definition: readfile.c:2610
static void oldnewmap_clear_map(OldNewMap *onm)
Definition: readfile.c:332
void BLO_expand_id(BlendExpander *expander, ID *id)
Definition: readfile.c:5805
static void after_liblink_merged_bmain_process(Main *bmain)
Definition: readfile.c:3973
static void direct_link_library(FileData *fd, Library *lib, Main *main)
Definition: readfile.c:3096
static void direct_link_id_override_property_cb(BlendDataReader *reader, void *data)
Definition: readfile.c:2335
void BLO_library_link_end(Main *mainl, BlendHandle **bh, const struct LibraryLink_Params *params)
Definition: readfile.c:5258
BlendFileData * blo_read_file_internal(FileData *fd, const char *filepath)
Definition: readfile.c:4097
static ID * link_named_part(Main *mainl, FileData *fd, const short idcode, const char *name, const int flag)
Definition: readfile.c:4878
static void convert_pointer_array_64_to_32(BlendDataReader *reader, uint array_size, const uint64_t *src, uint32_t *dst)
Definition: readfile.c:5696
static void lib_link_window_scene_data_restore(wmWindow *win, Scene *scene, ViewLayer *view_layer)
Definition: readfile.c:2749
static void blo_cache_storage_entry_clear_in_old(ID *UNUSED(id), const IDCacheKey *key, void **cache_p, uint UNUSED(flags), void *cache_storage_v)
Definition: readfile.c:2060
static void read_file_bhead_idname_map_create(FileData *fd)
Definition: readfile.c:576
static int direct_link_id_restore_recalc_exceptions(const ID *id_current)
Definition: readfile.c:2380
struct BLOCacheStorage BLOCacheStorage
static int lib_link_main_data_restore_cb(LibraryIDLinkCallbackData *cb_data)
Definition: readfile.c:2702
struct BlendExpander BlendExpander
static ssize_t fd_read_gzip_from_file(FileData *filedata, void *buffer, size_t size, bool *UNUSED(r_is_memchunck_identical))
Definition: readfile.c:1168
static void split_main_newid(Main *mainptr, Main *main_newid)
Definition: readfile.c:5117
static void link_global(FileData *fd, BlendFileData *bfd)
Definition: readfile.c:3809
void * BLO_read_get_new_packed_address(BlendDataReader *reader, const void *old_address)
Definition: readfile.c:5610
void BLO_library_link_params_init(struct LibraryLink_Params *params, struct Main *bmain, const int flag, const int id_tag_extra)
Definition: readfile.c:5069
static bool read_libblock_is_identical(FileData *fd, BHead *bhead)
Definition: readfile.c:3389
void * BLO_read_get_new_data_address_no_us(BlendDataReader *reader, const void *old_address)
Definition: readfile.c:5605
static BLOExpandDoitCallback expand_doit
Definition: readfile.c:4531
void blo_lib_link_restore(Main *oldmain, Main *newmain, wmWindowManager *curwm, Scene *curscene, ViewLayer *cur_view_layer)
Definition: readfile.c:3030
static int direct_link_id_restore_recalc(const FileData *fd, const ID *id_target, const ID *id_current, const bool is_identical)
Definition: readfile.c:2391
static void lib_link_clipboard_restore(struct IDNameLib_Map *id_map)
Definition: readfile.c:2696
static ID * create_placeholder(Main *mainvar, const short idcode, const char *idname, const int tag)
Definition: readfile.c:3190
static void * read_struct(FileData *fd, BHead *bh, const char *blockname)
Definition: readfile.c:2173
void BLO_library_link_params_init_with_context(struct LibraryLink_Params *params, struct Main *bmain, const int flag, const int id_tag_extra, struct Scene *scene, struct ViewLayer *view_layer, const struct View3D *v3d)
Definition: readfile.c:5080
Main * BLO_library_link_begin(BlendHandle **bh, const char *filepath, const struct LibraryLink_Params *params)
Definition: readfile.c:5109
int BLO_library_link_copypaste(Main *mainl, BlendHandle *bh, const uint64_t id_types_mask)
Definition: readfile.c:4941
static void do_versions_userdef(FileData *UNUSED(fd), BlendFileData *bfd)
Definition: readfile.c:3828
static bool blo_bhead_is_id(const BHead *bhead)
Definition: readfile.c:558
static FileData * blo_decode_and_check(FileData *fd, ReportList *reports)
Definition: readfile.c:1348
static void * restore_pointer_by_name(struct IDNameLib_Map *id_map, ID *id, ePointerUserMode user)
Definition: readfile.c:2658
static Main * library_link_begin(Main *mainvar, FileData **fd, const char *filepath, const int flag, const int id_tag_extra)
Definition: readfile.c:5034
static void direct_link_id_embedded_id(BlendDataReader *reader, Library *current_library, ID *id, ID *id_old)
Definition: readfile.c:2349
void BLO_read_glob_list(BlendDataReader *reader, ListBase *list)
Definition: readfile.c:5780
static int has_linked_ids_to_read(Main *mainvar)
Definition: readfile.c:5282
static bool direct_link_id(FileData *fd, Main *main, const int tag, ID *id, ID *id_old)
Definition: readfile.c:3312
static int lib_link_seq_clipboard_cb(Sequence *seq, void *arg_pt)
Definition: readfile.c:2684
static void library_link_clear_tag(Main *mainvar, const int flag)
Definition: readfile.c:5023
static void split_libdata(ListBase *lb_src, Main **lib_main_array, const uint lib_main_array_len)
Definition: readfile.c:474
void BLO_read_double_array(BlendDataReader *reader, int array_size, double **ptr_p)
Definition: readfile.c:5688
static void add_main_to_main(Main *mainvar, Main *from)
Definition: readfile.c:450
bool BLO_read_data_is_undo(BlendDataReader *reader)
Definition: readfile.c:5770
static void do_versions_after_linking(Main *main, ReportList *reports)
Definition: readfile.c:3881
static void direct_link_id_common(BlendDataReader *reader, Library *current_library, ID *id, ID *id_old, const int tag)
Definition: readfile.c:2437
static void * oldnewmap_lookup_and_inc(OldNewMap *onm, const void *addr, bool increase_users)
Definition: readfile.c:385
#define ENTRIES_CAPACITY(onm)
Definition: readfile.c:274
static BHead * find_bhead(FileData *fd, void *old)
Definition: readfile.c:4332
void BLO_read_float_array(BlendDataReader *reader, int array_size, float **ptr_p)
Definition: readfile.c:5675
void BLO_read_int32_array(BlendDataReader *reader, int array_size, int32_t **ptr_p)
Definition: readfile.c:5659
static const char * dataname(short id_code)
Definition: readfile.c:3225
void BLO_main_expander(BLOExpandDoitCallback expand_doit_func)
Definition: readfile.c:4575
#define DEBUG_PRINTF(...)
Definition: readfile.c:193
FileData * blo_filedata_from_file(const char *filepath, ReportList *reports)
Definition: readfile.c:1470
static void library_link_end(Main *mainl, FileData **fd, Main *bmain, const int flag, Scene *scene, ViewLayer *view_layer, const View3D *v3d)
Definition: readfile.c:5147
static void lib_link_main_data_restore(struct IDNameLib_Map *id_map, Main *newmain)
Definition: readfile.c:2734
ReportList * BLO_read_data_reports(BlendDataReader *reader)
Definition: readfile.c:5785
static void blo_cache_storage_entry_register(ID *id, const IDCacheKey *key, void **UNUSED(cache_p), uint UNUSED(flags), void *cache_storage_v)
Definition: readfile.c:2017
static BHead * find_bhead_from_idname(FileData *fd, const char *idname)
Definition: readfile.c:4395
static bool object_in_any_collection(Main *bmain, Object *ob)
Definition: readfile.c:4638
void BLO_read_list(BlendDataReader *reader, struct ListBase *list)
Definition: readfile.c:5654
static ssize_t fd_read_gzip_from_memory(FileData *filedata, void *buffer, size_t size, bool *UNUSED(r_is_memchunck_identical))
Definition: readfile.c:1499
static void * newdataadr_no_us(FileData *fd, const void *adr)
Definition: readfile.c:1812
struct OldNewMap OldNewMap
struct BlendDataReader BlendDataReader
static void add_loose_object_data_to_scene(Main *mainvar, Main *bmain, Scene *scene, ViewLayer *view_layer, const View3D *v3d, const short flag)
Definition: readfile.c:4741
void * blo_do_versions_newlibadr(FileData *fd, const void *lib, const void *adr)
Definition: readfile.c:1840
static void sort_bhead_old_map(FileData *fd)
Definition: readfile.c:4291
static bool read_libblock_undo_restore_linked(FileData *fd, Main *main, const ID *id, BHead *bhead)
Definition: readfile.c:3448
#define DEFAULT_SIZE_EXP
Definition: readfile.c:277
static void fix_relpaths_library(const char *basepath, Main *main)
Definition: readfile.c:3156
static BHead * find_previous_lib(FileData *fd, BHead *bhead)
Definition: readfile.c:4316
static void expand_doit_library(void *fdhandle, Main *mainvar, void *old)
Definition: readfile.c:4417
static void * newdataadr(FileData *fd, const void *adr)
Definition: readfile.c:1806
static bool read_libblock_undo_restore(FileData *fd, Main *main, BHead *bhead, const int tag, ID **r_id_old)
Definition: readfile.c:3551
bool BLO_read_lib_is_undo(BlendLibReader *reader)
Definition: readfile.c:5790
static void expand_id_embedded_id(BlendExpander *expander, ID *id)
Definition: readfile.c:4535
static FileData * read_library_file_data(FileData *basefd, ListBase *mainlist, Main *mainl, Main *mainptr)
Definition: readfile.c:5419
void * BLO_read_get_new_data_address(BlendDataReader *reader, const void *old_address)
Definition: readfile.c:5600
ReportList * BLO_read_lib_reports(BlendLibReader *reader)
Definition: readfile.c:5800
static bool read_libblock_undo_restore_library(FileData *fd, Main *main, const ID *id)
Definition: readfile.c:3411
static void oldnewmap_free(OldNewMap *onm)
Definition: readfile.c:430
static void * oldnewmap_liblookup(OldNewMap *onm, const void *addr, const void *lib)
Definition: readfile.c:398
static void lib_link_id_embedded_id(BlendLibReader *reader, ID *id)
Definition: readfile.c:2287
void BLO_read_uint32_array(BlendDataReader *reader, int array_size, uint32_t **ptr_p)
Definition: readfile.c:5667
static OldNewMap * oldnewmap_new(void)
Definition: readfile.c:350
static void expand_id(BlendExpander *expander, ID *id)
Definition: readfile.c:4553
static void oldnewmap_insert(OldNewMap *onm, const void *oldaddr, void *newaddr, int nr)
Definition: readfile.c:363
void blo_clear_proxy_pointers_from_lib(Main *oldmain)
Definition: readfile.c:1887
static int * read_file_thumbnail(FileData *fd)
Definition: readfile.c:1095
void BLO_read_data_globmap_add(BlendDataReader *reader, void *oldaddr, void *newaddr)
Definition: readfile.c:5775
static BHead * read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead)
Definition: readfile.c:4004
static void * newpackedadr(FileData *fd, const void *adr)
Definition: readfile.c:1824
static FileData * filedata_new(void)
Definition: readfile.c:1332
BlendThumbnail * BLO_thumbnail_from_file(const char *filepath)
Definition: readfile.c:1769
ID * BLO_read_get_new_id_address(BlendLibReader *reader, Library *lib, ID *id)
Definition: readfile.c:5615
static void read_library_linked_id(FileData *basefd, FileData *fd, Main *mainvar, ID *id, ID **r_id)
Definition: readfile.c:5298
static void read_library_linked_ids(FileData *basefd, FileData *fd, ListBase *mainlist, Main *mainvar)
Definition: readfile.c:5345
void BLO_read_list_cb(BlendDataReader *reader, ListBase *list, BlendReadListFn callback)
Definition: readfile.c:5630
static void do_versions(FileData *fd, Library *lib, Main *main)
Definition: readfile.c:3839
#define ITER_SLOTS(onm, KEY, SLOT_NAME, INDEX_NAME)
Definition: readfile.c:281
#define BHEADN_FROM_BHEAD(bh)
Definition: readfile.c:215
static bool object_in_any_scene(Main *bmain, Object *ob)
Definition: readfile.c:4627
BHead * blo_bhead_first(FileData *fd)
Definition: readfile.c:894
static bool library_link_idcode_needs_tag_check(const short idcode, const int flag)
Definition: readfile.c:5004
static void change_link_placeholder_to_real_ID_pointer_fd(FileData *fd, const void *old, void *new)
Definition: readfile.c:1846
AssetMetaData * blo_bhead_id_asset_data_address(const FileData *fd, const BHead *bhead)
Definition: readfile.c:993
bool BLO_library_path_explode(const char *path, char *r_dir, char **r_group, char **r_name)
Definition: readfile.c:1701
bool BLO_read_requires_endian_switch(BlendDataReader *reader)
Definition: readfile.c:5620
FileData * blo_filedata_from_memory(const void *mem, int memsize, ReportList *reports)
Definition: readfile.c:1543
static int fd_read_gzip_from_memory_init(FileData *fd)
Definition: readfile.c:1525
static void direct_link_keymapitem(BlendDataReader *reader, wmKeyMapItem *kmi)
Definition: readfile.c:3996
void * BLO_library_read_struct(FileData *fd, BHead *bh, const char *blockname)
Definition: readfile.c:5271
void blo_split_main(ListBase *mainlist, Main *main)
Definition: readfile.c:496
static int verg_bheadsort(const void *v1, const void *v2)
Definition: readfile.c:4278
struct OldNew OldNew
static bool read_file_dna(FileData *fd, const char **r_error_message)
Definition: readfile.c:1044
static ssize_t fd_read_from_memory(FileData *filedata, void *buffer, size_t size, bool *UNUSED(r_is_memchunck_identical))
Definition: readfile.c:1189
void blo_do_versions_key_uidgen(Key *key)
Definition: readfile.c:2529
BHead * blo_bhead_next(FileData *fd, BHead *thisblock)
Definition: readfile.c:922
static void placeholders_ensure_valid(Main *bmain)
Definition: readfile.c:3213
static BHead * find_bhead_from_code_name(FileData *fd, const short idcode, const char *name)
Definition: readfile.c:4365
void blo_cache_storage_init(FileData *fd, Main *bmain)
Definition: readfile.c:2078
void blo_make_old_idmap_from_main(FileData *fd, Main *bmain)
Definition: readfile.c:2003
static BHeadN * get_bhead(FileData *fd)
Definition: readfile.c:756
ePointerUserMode
Definition: readfile.c:2605
@ USER_REAL
Definition: readfile.c:2607
@ USER_IGNORE
Definition: readfile.c:2606
Main * BLO_read_lib_get_main(BlendLibReader *reader)
Definition: readfile.c:5795
static void oldnewmap_clear(OldNewMap *onm)
Definition: readfile.c:414
const char * blo_bhead_id_name(const FileData *fd, const BHead *bhead)
Definition: readfile.c:987
FileData * blo_filedata_from_memfile(MemFile *memfile, const struct BlendFileReadParams *params, ReportList *reports)
Definition: readfile.c:1572
static void oldnewmap_insert_or_replace(OldNewMap *onm, OldNew entry)
Definition: readfile.c:301
static void decode_blender_header(FileData *fd)
Definition: readfile.c:1001
static void read_libblock_undo_restore_at_old_address(FileData *fd, Main *main, ID *id, ID *id_old)
Definition: readfile.c:3519
static void bh4_from_bh8(BHead *bhead, BHead8 *bhead8, bool do_endian_swap)
Definition: readfile.c:716
void blo_end_packed_pointer_map(FileData *fd, Main *oldmain)
Definition: readfile.c:1948
static void lib_link_library(BlendLibReader *UNUSED(reader), Library *UNUSED(lib))
Definition: readfile.c:3150
#define MAP_CAPACITY(onm)
Definition: readfile.c:275
#define BHEAD_USE_READ_ON_DEMAND(bhead)
Definition: readfile.c:219
static void read_library_clear_weak_links(FileData *basefd, ListBase *mainlist, Main *mainvar)
Definition: readfile.c:5397
static off64_t fd_seek_data_from_file(FileData *filedata, off64_t offset, int whence)
Definition: readfile.c:1160
static FileData * blo_filedata_from_file_open(const char *filepath, ReportList *reports)
Definition: readfile.c:1449
static void change_link_placeholder_to_real_ID_pointer(ListBase *mainlist, FileData *basefd, void *old, void *new)
Definition: readfile.c:1860
bool BLO_has_bfile_extension(const char *str)
Definition: readfile.c:1684
static FileData * blo_filedata_from_file_descriptor(const char *filepath, ReportList *reports, int file)
Definition: readfile.c:1371
static void lib_link_id(BlendLibReader *reader, ID *id)
Definition: readfile.c:2306
BHead * blo_bhead_prev(FileData *UNUSED(fd), BHead *thisblock)
Definition: readfile.c:914
static ID * is_yet_read(FileData *fd, Main *mainvar, BHead *bhead)
Definition: readfile.c:4404
static void lib_link_seq_clipboard_pt_restore(ID *id, struct IDNameLib_Map *id_map)
Definition: readfile.c:2676
static void switch_endian_bh4(BHead4 *bhead)
Definition: readfile.c:688
void BLO_read_pointer_array(BlendDataReader *reader, void **ptr_p)
Definition: readfile.c:5727
static ssize_t fd_read_data_from_file(FileData *filedata, void *buffer, size_t size, bool *UNUSED(r_is_memchunck_identical))
Definition: readfile.c:1143
static OldNew * oldnewmap_lookup_entry(const OldNewMap *onm, const void *addr)
Definition: readfile.c:317
static void * newlibadr(FileData *fd, const void *lib, const void *adr)
Definition: readfile.c:1834
static BHead * read_global(BlendFileData *bfd, FileData *fd, BHead *bhead)
Definition: readfile.c:3762
static void switch_endian_bh8(BHead8 *bhead)
Definition: readfile.c:702
struct BHeadN BHeadN
static bool blo_bhead_read_data(FileData *fd, BHead *thisblock, void *buf)
Definition: readfile.c:949
static Main * blo_find_main(FileData *fd, const char *filepath, const char *relabase)
Definition: readfile.c:617
ID * BLO_library_link_named_part(Main *mainl, BlendHandle **bh, const short idcode, const char *name, const struct LibraryLink_Params *params)
Definition: readfile.c:4989
static void switch_endian_structs(const struct SDNA *filesdna, BHead *bhead)
Definition: readfile.c:2157
void blo_filedata_free(FileData *fd)
Definition: readfile.c:1591
static void lib_link_wm_xr_data_restore(struct IDNameLib_Map *id_map, wmXrData *xr_data)
Definition: readfile.c:2743
static void insert_packedmap(FileData *fd, PackedFile *pf)
Definition: readfile.c:1899
static bool blo_bhead_is_id_valid_type(const BHead *bhead)
Definition: readfile.c:565
static void oldnewmap_insert_index_in_map(OldNewMap *onm, const void *ptr, int index)
Definition: readfile.c:291
static const char * library_parent_filepath(Library *lib)
Definition: readfile.c:248
static void object_base_instance_init(Object *ob, bool set_selected, bool set_active, ViewLayer *view_layer, const View3D *v3d)
Definition: readfile.c:4659
static void read_libblock_undo_restore_identical(FileData *fd, Main *main, const ID *UNUSED(id), ID *id_old, const int tag)
Definition: readfile.c:3474
static void read_file_version(FileData *fd, Main *main)
Definition: readfile.c:534
void blo_cache_storage_old_bmain_clear(FileData *fd, Main *bmain_old)
Definition: readfile.c:2114
static void add_collections_to_scene(Main *mainvar, Main *bmain, Scene *scene, ViewLayer *view_layer, const View3D *v3d, Library *lib, const short flag)
Definition: readfile.c:4790
static ssize_t fd_read_from_memfile(FileData *filedata, void *buffer, size_t size, bool *r_is_memchunck_identical)
Definition: readfile.c:1252
static void lib_link_workspace_layout_restore(struct IDNameLib_Map *id_map, Main *newmain, WorkSpaceLayout *layout)
Definition: readfile.c:2798
BHead * blo_read_asset_data_block(FileData *fd, BHead *bhead, AssetMetaData **r_asset_data)
Definition: readfile.c:3739
void blo_add_library_pointer_map(ListBase *old_mainlist, FileData *fd)
Definition: readfile.c:1985
static FileData * blo_filedata_from_file_minimal(const char *filepath)
Definition: readfile.c:1486
void blo_join_main(ListBase *mainlist)
Definition: readfile.c:462
void * blo_read_get_new_globaldata_address(FileData *fd, const void *adr)
Definition: readfile.c:1818
static off64_t fd_seek_from_mmap(FileData *filedata, off64_t offset, int whence)
Definition: readfile.c:1226
static BHead * read_data_into_datamap(FileData *fd, BHead *bhead, const char *allocname)
Definition: readfile.c:3356
static void direct_link_id_override_property_operation_cb(BlendDataReader *reader, void *data)
Definition: readfile.c:2325
static void oldnewmap_increase_size(OldNewMap *onm)
Definition: readfile.c:337
static void blo_cache_storage_entry_restore_in_new(ID *UNUSED(id), const IDCacheKey *key, void **cache_p, uint flags, void *cache_storage_v)
Definition: readfile.c:2035
static const void * peek_struct_undo(FileData *fd, BHead *bhead)
Definition: readfile.c:2243
void do_versions_after_linking_250(struct Main *bmain)
ssize_t() FileDataReadFn(struct FileData *filedata, void *buffer, size_t size, bool *r_is_memchunk_identical)
Definition: readfile.h:67
@ FD_FLAGS_FILE_POINTSIZE_IS_4
Definition: readfile.h:50
@ FD_FLAGS_POINTSIZE_DIFFERS
Definition: readfile.h:51
@ FD_FLAGS_NOT_MY_LIBMAP
Definition: readfile.h:55
@ FD_FLAGS_FILE_OK
Definition: readfile.h:52
@ FD_FLAGS_SWITCH_ENDIAN
Definition: readfile.h:49
@ FD_FLAGS_NOT_MY_BUFFER
Definition: readfile.h:53
void blo_do_versions_pre250(struct FileData *fd, struct Library *lib, struct Main *bmain)
void blo_do_versions_dna(struct SDNA *sdna, const int versionfile, const int subversionfile)
void do_versions_after_linking_290(struct Main *bmain, struct ReportList *reports)
void blo_do_versions_250(struct FileData *fd, struct Library *lib, struct Main *bmain)
off64_t() FileDataSeekFn(struct FileData *filedata, off64_t offset, int whence)
Definition: readfile.h:71
void blo_do_versions_cycles(struct FileData *fd, struct Library *lib, struct Main *bmain)
void do_versions_after_linking_270(struct Main *bmain)
void do_versions_after_linking_260(struct Main *bmain)
void blo_do_versions_260(struct FileData *fd, struct Library *lib, struct Main *bmain)
void do_versions_after_linking_280(struct Main *bmain, struct ReportList *reports)
void blo_do_versions_290(struct FileData *fd, struct Library *lib, struct Main *bmain)
void do_versions_after_linking_cycles(struct Main *bmain)
void blo_do_versions_270(struct FileData *fd, struct Library *lib, struct Main *bmain)
#define SIZEOFBLENDERHEADER
Definition: readfile.h:155
void blo_do_versions_userdef(struct UserDef *userdef)
void blo_do_versions_280(struct FileData *fd, struct Library *lib, struct Main *bmain)
struct SELECTID_Context context
Definition: select_engine.c:47
#define SIZE_MAX
Definition: stdint.h:209
unsigned int uint32_t
Definition: stdint.h:83
__int64 int64_t
Definition: stdint.h:92
signed int int32_t
Definition: stdint.h:80
unsigned __int64 uint64_t
Definition: stdint.h:93
The meta-data of an asset. By creating and giving this for a data-block (ID.asset_data),...
uint64_t old
off64_t file_offset
Definition: readfile.c:207
struct BHeadN * prev
Definition: readfile.c:204
struct BHeadN * next
Definition: readfile.c:204
bool has_data
Definition: readfile.c:209
struct BHead bhead
Definition: readfile.c:212
bool is_memchunk_identical
Definition: readfile.c:211
const void * old
Definition: readfile.c:4275
BHead * bhead
Definition: readfile.c:4274
int SDNAnr
const void * old
MemArena * memarena
Definition: readfile.c:2013
GHash * cache_map
Definition: readfile.c:2012
struct Base * next
short flag
unsigned short local_view_bits
FileData * fd
Definition: readfile.c:675
FileData * fd
Definition: readfile.c:684
Main * main
Definition: readfile.c:685
struct bScreen * curscreen
Definition: BLO_readfile.h:77
eBlenFileType type
Definition: BLO_readfile.h:81
struct Scene * curscene
Definition: BLO_readfile.h:78
struct ViewLayer * cur_view_layer
Definition: BLO_readfile.h:79
struct Main * main
Definition: BLO_readfile.h:70
struct UserDef * user
Definition: BLO_readfile.h:71
char filename[1024]
Definition: BLO_readfile.h:75
Main * main
Definition: readfile.c:680
FileData * fd
Definition: readfile.c:679
char rect[0]
Definition: BKE_main.h:59
eBLOReadSkip skip_flags
Definition: readfile.h:121
int undo_direction
Definition: readfile.h:94
size_t buffersize
Definition: readfile.h:78
struct DNA_ReconstructInfo * reconstruct_info
Definition: readfile.h:109
int id_asset_data_offset
Definition: readfile.h:116
ListBase * old_mainlist
Definition: readfile.h:145
int library_id_missing_count
Definition: readfile.h:152
enum eFileDataFlag flags
Definition: readfile.h:76
ListBase bhead_list
Definition: readfile.h:75
FileDataSeekFn * seek
Definition: readfile.h:82
int fileversion
Definition: readfile.h:111
struct OldNewMap * globmap
Definition: readfile.h:132
struct OldNewMap * libmap
Definition: readfile.h:133
int fileflags
Definition: readfile.h:118
FileDataReadFn * read
Definition: readfile.h:81
z_stream strm
Definition: readfile.h:99
ListBase * mainlist
Definition: readfile.h:143
struct MemFile * memfile
Definition: readfile.h:91
const struct SDNA * memsdna
Definition: readfile.h:106
struct SDNA * filesdna
Definition: readfile.h:105
int id_tag_extra
Definition: readfile.h:129
char relabase[FILE_MAX]
Definition: readfile.h:102
struct OldNewMap * datamap
Definition: readfile.h:131
struct ReportList * reports
Definition: readfile.h:148
struct GHash * bhead_idname_hash
Definition: readfile.h:141
const char * compflags
Definition: readfile.h:108
const char * buffer
Definition: readfile.h:88
int globalf
Definition: readfile.h:118
off64_t file_offset
Definition: readfile.h:79
int id_name_offset
Definition: readfile.h:113
bool is_eof
Definition: readfile.h:77
gzFile gzfiledes
Definition: readfile.h:97
int tot_bheadmap
Definition: readfile.h:138
struct OldNewMap * packedmap
Definition: readfile.h:134
int filedes
Definition: readfile.h:85
struct BLI_mmap_file * mmap_file
Definition: readfile.h:89
struct BLOCacheStorage * cache_storage
Definition: readfile.h:135
int library_file_missing_count
Definition: readfile.h:151
struct BHeadSort * bheadmap
Definition: readfile.h:137
struct IDNameLib_Map * old_idmap
Definition: readfile.h:146
struct ViewLayer * cur_view_layer
struct Scene * curscene
uint64_t build_commit_timestamp
struct bScreen * curscreen
char filename[1024]
unsigned int id_session_uuid
Definition: BKE_idtype.h:56
void * cache_v
Definition: BKE_idtype.h:61
struct Main * bmain
Definition: main_idmap.c:71
struct ID * storage
Definition: DNA_ID.h:257
ListBase properties
Definition: DNA_ID.h:252
struct ID * reference
Definition: DNA_ID.h:250
IDTypeBlendReadUndoPreserve blend_read_undo_preserve
Definition: BKE_idtype.h:218
IDTypeBlendReadExpandFunction blend_read_expand
Definition: BKE_idtype.h:211
IDTypeForeachCacheFunction foreach_cache
Definition: BKE_idtype.h:184
IDTypeBlendReadDataFunction blend_read_data
Definition: BKE_idtype.h:201
IDTypeBlendReadLibFunction blend_read_lib
Definition: BKE_idtype.h:206
Definition: DNA_ID.h:273
int tag
Definition: DNA_ID.h:292
struct AssetMetaData * asset_data
Definition: DNA_ID.h:280
struct Library * lib
Definition: DNA_ID.h:277
int recalc_after_undo_push
Definition: DNA_ID.h:306
int recalc
Definition: DNA_ID.h:295
int us
Definition: DNA_ID.h:293
int icon_id
Definition: DNA_ID.h:294
struct ID * newid
Definition: DNA_ID.h:275
IDProperty * properties
Definition: DNA_ID.h:314
IDOverrideLibrary * override_library
Definition: DNA_ID.h:317
struct ID * orig_id
Definition: DNA_ID.h:324
short flag
Definition: DNA_ID.h:288
unsigned int session_uuid
Definition: DNA_ID.h:312
void * next
Definition: DNA_ID.h:274
char name[66]
Definition: DNA_ID.h:283
int recalc_up_to_undo_push
Definition: DNA_ID.h:305
struct Scene * scene
int uidgen
ListBase block
struct Collection * collection
struct PackedFile * packedfile
Definition: DNA_ID.h:367
short versionfile
Definition: DNA_ID.h:372
short subversionfile
Definition: DNA_ID.h:372
char filepath[1024]
Definition: DNA_ID.h:352
ID id
Definition: DNA_ID.h:349
int temp_index
Definition: DNA_ID.h:370
struct Library * parent
Definition: DNA_ID.h:365
struct FileData * filedata
Definition: DNA_ID.h:350
char filepath_abs[1024]
Definition: DNA_ID.h:362
void * last
Definition: DNA_listBase.h:47
void * first
Definition: DNA_listBase.h:47
Definition: BKE_main.h:116
ListBase volumes
Definition: BKE_main.h:184
ListBase scenes
Definition: BKE_main.h:146
short subversionfile
Definition: BKE_main.h:119
ListBase texts
Definition: BKE_main.h:163
ListBase fonts
Definition: BKE_main.h:162
BlendThumbnail * blen_thumb
Definition: BKE_main.h:143
short minversionfile
Definition: BKE_main.h:120
uint64_t build_commit_timestamp
Definition: BKE_main.h:121
struct Main * next
Definition: BKE_main.h:117
ListBase sounds
Definition: BKE_main.h:166
ListBase libraries
Definition: BKE_main.h:147
char name[1024]
Definition: BKE_main.h:118
char build_hash[16]
Definition: BKE_main.h:122
short minsubversionfile
Definition: BKE_main.h:120
short versionfile
Definition: BKE_main.h:119
ListBase workspaces
Definition: BKE_main.h:181
struct Main * prev
Definition: BKE_main.h:117
ListBase collections
Definition: BKE_main.h:167
ListBase images
Definition: BKE_main.h:154
ListBase objects
Definition: BKE_main.h:148
struct Library * curlib
Definition: BKE_main.h:145
struct Mask * mask
bool is_identical_future
Definition: BLO_undofile.h:40
bool is_identical
Definition: BLO_undofile.h:36
const char * buf
Definition: BLO_undofile.h:32
ListBase chunks
Definition: BLO_undofile.h:47
short transflag
struct Collection * instance_collection
struct Object * proxy_from
struct Object * proxy
float loc[3]
float empty_drawsize
void * data
OldNew * entries
Definition: readfile.c:266
int32_t * map
Definition: readfile.c:269
int capacity_exp
Definition: readfile.c:271
int nentries
Definition: readfile.c:267
int nr
Definition: readfile.c:261
void * newp
Definition: readfile.c:259
const void * oldp
Definition: readfile.c:258
struct RegionView3D * localvd
short * types_size
SDNA_Struct ** structs
const char ** types
int pointer_size
struct Collection * master_collection
short flag
View3DCursor cursor
struct Object * camera
struct Scene * set
float * waveform_3
float * waveform_2
float * waveform_1
float * vecscope
struct MovieClip * clip
struct Scene * scene
struct Object * scene_camera
struct Mask * mask
struct bSound * sound
bAction * action
bDopeSheet ads
SpaceAction_Runtime runtime
struct MovieClipScopes scopes
struct MovieClip * clip
MaskSpaceInfo mask_info
struct wmOperator * op
struct wmTimer * previews_timer
struct bDopeSheet * ads
SpaceGraph_Runtime runtime
struct Scopes scopes
MaskSpaceInfo mask_info
struct ImageUser iuser
struct bGPdata * gpd
struct Image * image
struct bDopeSheet * ads
struct ID * from
ListBase treepath
struct bNodeTree * edittree
struct ID * id
struct bNodeTree * nodetree
struct TreeStoreElem search_tse
struct BLI_mempool * treestore
struct Script * script
struct bGPdata * gpd
struct Text * text
struct ListBase addons
struct ListBase uistyles
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 user_menus
struct ListBase asset_libraries
char app_template[64]
UserDef_Runtime runtime
unsigned short local_view_uuid
struct Object * camera
struct View3D * localvd
short scenelock
struct Object * ob_center
struct Base * basact
ListBase object_bases
char name[64]
Wrapper for bScreen.
Object * base_pose_object
Definition: DNA_xr_types.h:37
struct Collection * filter_grp
struct bNodeTree * nodetree
struct bNodeTreePath * next
ListBase areabase
struct IDProperty * prop
struct PointerRNA * ptr
struct WorkSpaceInstanceHook * workspace_hook
XrSessionSettings session_settings
#define G(x, y, z)
PointerRNA * ptr
Definition: wm_files.c:3157