Blender  V2.93
readblenentry.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  * .blend file reading entry point
19  */
20 
25 #include <stddef.h>
26 
27 #include <math.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 
32 #include "MEM_guardedalloc.h"
33 
34 #include "BLI_ghash.h"
35 #include "BLI_linklist.h"
36 #include "BLI_listbase.h"
37 #include "BLI_string.h"
38 #include "BLI_utildefines.h"
39 
40 #include "DNA_genfile.h"
41 #include "DNA_sdna_types.h"
42 
43 #include "BKE_icons.h"
44 #include "BKE_idtype.h"
45 #include "BKE_main.h"
46 
47 #include "BLO_blend_defs.h"
48 #include "BLO_readfile.h"
49 #include "BLO_undofile.h"
50 
51 #include "readfile.h"
52 
53 #include "BLI_sys_types.h" // needed for intptr_t
54 
55 #ifdef WIN32
56 # include "BLI_winstuff.h"
57 #endif
58 
59 /* local prototypes --------------------- */
60 void BLO_blendhandle_print_sizes(BlendHandle *bh, void *fp);
61 
62 /* Access routines used by filesel. */
63 
71 BlendHandle *BLO_blendhandle_from_file(const char *filepath, ReportList *reports)
72 {
73  BlendHandle *bh;
74 
75  bh = (BlendHandle *)blo_filedata_from_file(filepath, reports);
76 
77  return bh;
78 }
79 
87 BlendHandle *BLO_blendhandle_from_memory(const void *mem, int memsize)
88 {
89  BlendHandle *bh;
90 
91  bh = (BlendHandle *)blo_filedata_from_memory(mem, memsize, NULL);
92 
93  return bh;
94 }
95 
97 {
98  FileData *fd = (FileData *)bh;
99  BHead *bhead;
100 
101  fprintf(fp, "[\n");
102  for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
103  if (bhead->code == ENDB) {
104  break;
105  }
106 
107  const SDNA_Struct *struct_info = fd->filesdna->structs[bhead->SDNAnr];
108  const char *name = fd->filesdna->types[struct_info->type];
109  char buf[4];
110 
111  buf[0] = (bhead->code >> 24) & 0xFF;
112  buf[1] = (bhead->code >> 16) & 0xFF;
113  buf[2] = (bhead->code >> 8) & 0xFF;
114  buf[3] = (bhead->code >> 0) & 0xFF;
115 
116  buf[0] = buf[0] ? buf[0] : ' ';
117  buf[1] = buf[1] ? buf[1] : ' ';
118  buf[2] = buf[2] ? buf[2] : ' ';
119  buf[3] = buf[3] ? buf[3] : ' ';
120 
121  fprintf(fp,
122  "['%.4s', '%s', %d, %ld ],\n",
123  buf,
124  name,
125  bhead->nr,
126  (long int)(bhead->len + sizeof(BHead)));
127  }
128  fprintf(fp, "]\n");
129 }
130 
142  int ofblocktype,
143  const bool use_assets_only,
144  int *r_tot_names)
145 {
146  FileData *fd = (FileData *)bh;
147  LinkNode *names = NULL;
148  BHead *bhead;
149  int tot = 0;
150 
151  for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
152  if (bhead->code == ofblocktype) {
153  const char *idname = blo_bhead_id_name(fd, bhead);
154  if (use_assets_only && blo_bhead_id_asset_data_address(fd, bhead) == NULL) {
155  continue;
156  }
157 
158  BLI_linklist_prepend(&names, BLI_strdup(idname + 2));
159  tot++;
160  }
161  else if (bhead->code == ENDB) {
162  break;
163  }
164  }
165 
166  *r_tot_names = tot;
167  return names;
168 }
169 
181  int ofblocktype,
182  int *r_tot_info_items)
183 {
184  FileData *fd = (FileData *)bh;
185  LinkNode *infos = NULL;
186  BHead *bhead;
187  int tot = 0;
188 
189  for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
190  if (bhead->code == ofblocktype) {
191  struct BLODataBlockInfo *info = MEM_mallocN(sizeof(*info), __func__);
192  const char *name = blo_bhead_id_name(fd, bhead) + 2;
193 
194  STRNCPY(info->name, name);
195 
196  /* Lastly, read asset data from the following blocks. */
197  info->asset_data = blo_bhead_id_asset_data_address(fd, bhead);
198  if (info->asset_data) {
199  bhead = blo_read_asset_data_block(fd, bhead, &info->asset_data);
200  /* blo_read_asset_data_block() reads all DATA heads and already advances bhead to the next
201  * non-DATA one. Go back, so the loop doesn't skip the non-DATA head. */
202  bhead = blo_bhead_prev(fd, bhead);
203  }
204 
205  BLI_linklist_prepend(&infos, info);
206  tot++;
207  }
208  else if (bhead->code == ENDB) {
209  break;
210  }
211  }
212 
213  *r_tot_info_items = tot;
214  return infos;
215 }
216 
226 LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *r_tot_prev)
227 {
228  FileData *fd = (FileData *)bh;
229  LinkNode *previews = NULL;
230  BHead *bhead;
231  int looking = 0;
232  PreviewImage *prv = NULL;
233  PreviewImage *new_prv = NULL;
234  int tot = 0;
235 
236  for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
237  if (bhead->code == ofblocktype) {
238  const char *idname = blo_bhead_id_name(fd, bhead);
239  switch (GS(idname)) {
240  case ID_MA: /* fall through */
241  case ID_TE: /* fall through */
242  case ID_IM: /* fall through */
243  case ID_WO: /* fall through */
244  case ID_LA: /* fall through */
245  case ID_OB: /* fall through */
246  case ID_GR: /* fall through */
247  case ID_SCE: /* fall through */
248  case ID_AC: /* fall through */
249  new_prv = MEM_callocN(sizeof(PreviewImage), "newpreview");
250  BLI_linklist_prepend(&previews, new_prv);
251  tot++;
252  looking = 1;
253  break;
254  default:
255  break;
256  }
257  }
258  else if (bhead->code == DATA) {
259  if (looking) {
260  if (bhead->SDNAnr == DNA_struct_find_nr(fd->filesdna, "PreviewImage")) {
261  prv = BLO_library_read_struct(fd, bhead, "PreviewImage");
262 
263  if (prv) {
264  memcpy(new_prv, prv, sizeof(PreviewImage));
265  if (prv->rect[0] && prv->w[0] && prv->h[0]) {
266  bhead = blo_bhead_next(fd, bhead);
267  BLI_assert((new_prv->w[0] * new_prv->h[0] * sizeof(uint)) == bhead->len);
268  new_prv->rect[0] = BLO_library_read_struct(fd, bhead, "PreviewImage Icon Rect");
269  }
270  else {
271  /* This should not be needed, but can happen in 'broken' .blend files,
272  * better handle this gracefully than crashing. */
273  BLI_assert(prv->rect[0] == NULL && prv->w[0] == 0 && prv->h[0] == 0);
274  new_prv->rect[0] = NULL;
275  new_prv->w[0] = new_prv->h[0] = 0;
276  }
277  BKE_previewimg_finish(new_prv, 0);
278 
279  if (prv->rect[1] && prv->w[1] && prv->h[1]) {
280  bhead = blo_bhead_next(fd, bhead);
281  BLI_assert((new_prv->w[1] * new_prv->h[1] * sizeof(uint)) == bhead->len);
282  new_prv->rect[1] = BLO_library_read_struct(fd, bhead, "PreviewImage Image Rect");
283  }
284  else {
285  /* This should not be needed, but can happen in 'broken' .blend files,
286  * better handle this gracefully than crashing. */
287  BLI_assert(prv->rect[1] == NULL && prv->w[1] == 0 && prv->h[1] == 0);
288  new_prv->rect[1] = NULL;
289  new_prv->w[1] = new_prv->h[1] = 0;
290  }
291  BKE_previewimg_finish(new_prv, 1);
292  MEM_freeN(prv);
293  }
294  }
295  }
296  }
297  else if (bhead->code == ENDB) {
298  break;
299  }
300  else {
301  looking = 0;
302  new_prv = NULL;
303  prv = NULL;
304  }
305  }
306 
307  *r_tot_prev = tot;
308  return previews;
309 }
310 
319 {
320  FileData *fd = (FileData *)bh;
321  GSet *gathered = BLI_gset_ptr_new("linkable_groups gh");
322  LinkNode *names = NULL;
323  BHead *bhead;
324 
325  for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
326  if (bhead->code == ENDB) {
327  break;
328  }
329  if (BKE_idtype_idcode_is_valid(bhead->code)) {
330  if (BKE_idtype_idcode_is_linkable(bhead->code)) {
331  const char *str = BKE_idtype_idcode_to_name(bhead->code);
332 
333  if (BLI_gset_add(gathered, (void *)str)) {
335  }
336  }
337  }
338  }
339 
340  BLI_gset_free(gathered, NULL);
341 
342  return names;
343 }
344 
351 {
352  FileData *fd = (FileData *)bh;
353 
354  blo_filedata_free(fd);
355 }
356 
357 /**********/
358 
367 BlendFileData *BLO_read_from_file(const char *filepath,
368  eBLOReadSkip skip_flags,
369  ReportList *reports)
370 {
371  BlendFileData *bfd = NULL;
372  FileData *fd;
373 
374  fd = blo_filedata_from_file(filepath, reports);
375  if (fd) {
376  fd->reports = reports;
377  fd->skip_flags = skip_flags;
378  bfd = blo_read_file_internal(fd, filepath);
379  blo_filedata_free(fd);
380  }
381 
382  return bfd;
383 }
384 
395  int memsize,
396  eBLOReadSkip skip_flags,
397  ReportList *reports)
398 {
399  BlendFileData *bfd = NULL;
400  FileData *fd;
401 
402  fd = blo_filedata_from_memory(mem, memsize, reports);
403  if (fd) {
404  fd->reports = reports;
405  fd->skip_flags = skip_flags;
406  bfd = blo_read_file_internal(fd, "");
407  blo_filedata_free(fd);
408  }
409 
410  return bfd;
411 }
412 
422  const char *filename,
423  MemFile *memfile,
424  const struct BlendFileReadParams *params,
425  ReportList *reports)
426 {
427  BlendFileData *bfd = NULL;
428  FileData *fd;
429  ListBase old_mainlist;
430 
431  fd = blo_filedata_from_memfile(memfile, params, reports);
432  if (fd) {
433  fd->reports = reports;
434  fd->skip_flags = params->skip_flags;
435  BLI_strncpy(fd->relabase, filename, sizeof(fd->relabase));
436 
437  /* clear ob->proxy_from pointers in old main */
439 
440  /* separate libraries from old main */
441  blo_split_main(&old_mainlist, oldmain);
442  /* add the library pointers in oldmap lookup */
443  blo_add_library_pointer_map(&old_mainlist, fd);
444 
445  if ((params->skip_flags & BLO_READ_SKIP_UNDO_OLD_MAIN) == 0) {
446  /* Build idmap of old main (we only care about local data here, so we can do that after
447  * split_main() call. */
448  blo_make_old_idmap_from_main(fd, old_mainlist.first);
449  }
450 
451  /* removed packed data from this trick - it's internal data that needs saves */
452 
453  /* Store all existing ID caches pointers into a mapping, to allow restoring them into newly
454  * read IDs whenever possible. */
455  blo_cache_storage_init(fd, oldmain);
456 
457  bfd = blo_read_file_internal(fd, filename);
458 
459  /* Ensure relinked caches are not freed together with their old IDs. */
461 
462  /* Still in-use libraries have already been moved from oldmain to new mainlist,
463  * but oldmain itself shall *never* be 'transferred' to new mainlist! */
464  BLI_assert(old_mainlist.first == oldmain);
465 
466  /* That way, libs (aka mains) we did not reuse in new undone/redone state
467  * will be cleared together with oldmain... */
468  blo_join_main(&old_mainlist);
469 
470  blo_filedata_free(fd);
471  }
472 
473  return bfd;
474 }
475 
483 {
484  if (bfd->main) {
485  BKE_main_free(bfd->main);
486  }
487 
488  if (bfd->user) {
489  MEM_freeN(bfd->user);
490  }
491 
492  MEM_freeN(bfd);
493 }
void BKE_previewimg_finish(struct PreviewImage *prv, const int size)
Definition: icons.cc:614
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
const char * BKE_idtype_idcode_to_name(const short idcode)
Definition: idtype.c:168
void BKE_main_free(struct Main *mainvar)
Definition: main.c:53
#define BLI_assert(a)
Definition: BLI_assert.h:58
struct GSet GSet
Definition: BLI_ghash.h:189
GSet * BLI_gset_ptr_new(const char *info)
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
Definition: BLI_ghash.c:1253
bool BLI_gset_add(GSet *gs, void *key)
Definition: BLI_ghash.c:1160
#define STRNCPY(dst, src)
Definition: BLI_string.h:163
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC
Definition: string.c:70
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
Compatibility-like things for windows.
defines for blend-file codes.
@ ENDB
@ DATA
external readfile function prototypes.
eBLOReadSkip
Definition: BLO_readfile.h:93
@ BLO_READ_SKIP_UNDO_OLD_MAIN
Definition: BLO_readfile.h:98
struct BlendHandle BlendHandle
Definition: BLO_readfile.h:49
void * BLO_library_read_struct(struct FileData *fd, struct BHead *bh, const char *blockname)
Definition: readfile.c:5271
@ ID_TE
Definition: DNA_ID_enums.h:64
@ ID_IM
Definition: DNA_ID_enums.h:65
@ ID_LA
Definition: DNA_ID_enums.h:67
@ ID_SCE
Definition: DNA_ID_enums.h:57
@ ID_WO
Definition: DNA_ID_enums.h:71
@ ID_MA
Definition: DNA_ID_enums.h:63
@ ID_AC
Definition: DNA_ID_enums.h:79
@ ID_GR
Definition: DNA_ID_enums.h:77
@ ID_OB
Definition: DNA_ID_enums.h:59
blenloader genfile private function prototypes
int DNA_struct_find_nr(const struct SDNA *sdna, const char *str)
Read Guarded memory(de)allocation.
#define str(s)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
#define GS(x)
Definition: iris.c:241
static char ** names
Definition: makesdna.c:162
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
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
BlendFileData * BLO_read_from_memory(const void *mem, int memsize, eBLOReadSkip skip_flags, ReportList *reports)
BlendFileData * BLO_read_from_memfile(Main *oldmain, const char *filename, MemFile *memfile, const struct BlendFileReadParams *params, ReportList *reports)
LinkNode * BLO_blendhandle_get_datablock_info(BlendHandle *bh, int ofblocktype, int *r_tot_info_items)
BlendHandle * BLO_blendhandle_from_file(const char *filepath, ReportList *reports)
Definition: readblenentry.c:71
BlendFileData * BLO_read_from_file(const char *filepath, eBLOReadSkip skip_flags, ReportList *reports)
BlendHandle * BLO_blendhandle_from_memory(const void *mem, int memsize)
Definition: readblenentry.c:87
LinkNode * BLO_blendhandle_get_linkable_groups(BlendHandle *bh)
void BLO_blendhandle_print_sizes(BlendHandle *bh, void *fp)
Definition: readblenentry.c:96
LinkNode * BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *r_tot_prev)
LinkNode * BLO_blendhandle_get_datablock_names(BlendHandle *bh, int ofblocktype, const bool use_assets_only, int *r_tot_names)
void BLO_blendhandle_close(BlendHandle *bh)
void BLO_blendfiledata_free(BlendFileData *bfd)
BlendFileData * blo_read_file_internal(FileData *fd, const char *filepath)
Definition: readfile.c:4097
FileData * blo_filedata_from_file(const char *filepath, ReportList *reports)
Definition: readfile.c:1470
void blo_clear_proxy_pointers_from_lib(Main *oldmain)
Definition: readfile.c:1887
BHead * blo_bhead_first(FileData *fd)
Definition: readfile.c:894
AssetMetaData * blo_bhead_id_asset_data_address(const FileData *fd, const BHead *bhead)
Definition: readfile.c:993
FileData * blo_filedata_from_memory(const void *mem, int memsize, ReportList *reports)
Definition: readfile.c:1543
void blo_split_main(ListBase *mainlist, Main *main)
Definition: readfile.c:496
BHead * blo_bhead_next(FileData *fd, BHead *thisblock)
Definition: readfile.c:922
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
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
BHead * blo_bhead_prev(FileData *UNUSED(fd), BHead *thisblock)
Definition: readfile.c:914
void blo_filedata_free(FileData *fd)
Definition: readfile.c:1591
void blo_cache_storage_old_bmain_clear(FileData *fd, Main *bmain_old)
Definition: readfile.c:2114
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
void blo_join_main(ListBase *mainlist)
Definition: readfile.c:462
int SDNAnr
struct AssetMetaData * asset_data
Definition: BLO_readfile.h:125
struct Main * main
Definition: BLO_readfile.h:70
struct UserDef * user
Definition: BLO_readfile.h:71
eBLOReadSkip skip_flags
Definition: readfile.h:121
struct SDNA * filesdna
Definition: readfile.h:105
char relabase[FILE_MAX]
Definition: readfile.h:102
struct ReportList * reports
Definition: readfile.h:148
void * first
Definition: DNA_listBase.h:47
Definition: BKE_main.h:116
unsigned int h[2]
Definition: DNA_ID.h:392
unsigned int * rect[2]
Definition: DNA_ID.h:395
unsigned int w[2]
Definition: DNA_ID.h:391
SDNA_Struct ** structs
const char ** types