2022-02-11 09:07:11 +11:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
|
* Copyright 2001-2002 NaN Holding BV. All rights reserved. */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup blenloader
|
2022-02-09 23:25:53 +11:00
|
|
|
* `.blend` file reading entry point.
|
2011-02-27 20:35:41 +00:00
|
|
|
*/
|
|
|
|
|
|
2010-09-15 06:43:36 +00:00
|
|
|
#include <stddef.h>
|
2009-09-06 15:13:57 +00:00
|
|
|
|
2020-03-19 09:33:03 +01:00
|
|
|
#include <math.h>
|
|
|
|
|
#include <stdio.h>
|
2002-10-12 11:37:38 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
|
|
#include "BLI_ghash.h"
|
|
|
|
|
#include "BLI_linklist.h"
|
2011-10-22 15:35:49 +00:00
|
|
|
#include "BLI_listbase.h"
|
|
|
|
|
#include "BLI_string.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BLI_utildefines.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2008-10-31 23:50:02 +00:00
|
|
|
#include "DNA_genfile.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "DNA_sdna_types.h"
|
|
|
|
|
|
2020-12-14 13:21:58 +01:00
|
|
|
#include "BKE_icons.h"
|
2020-03-19 19:37:00 +01:00
|
|
|
#include "BKE_idtype.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BKE_main.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BLO_blend_defs.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "BLO_readfile.h"
|
2004-09-05 13:43:51 +00:00
|
|
|
#include "BLO_undofile.h"
|
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "readfile.h"
|
|
|
|
|
|
2021-08-31 13:36:28 +10:00
|
|
|
#include "BLI_sys_types.h" /* Needed for `intptr_t`. */
|
2008-08-17 16:36:37 +00:00
|
|
|
|
2012-04-15 07:54:07 +00:00
|
|
|
#ifdef WIN32
|
|
|
|
|
# include "BLI_winstuff.h"
|
2009-09-06 13:20:05 +00:00
|
|
|
#endif
|
|
|
|
|
|
2005-03-09 19:45:59 +00:00
|
|
|
/* local prototypes --------------------- */
|
2020-07-03 17:07:01 +02:00
|
|
|
void BLO_blendhandle_print_sizes(BlendHandle *bh, void *fp);
|
2005-03-09 19:45:59 +00:00
|
|
|
|
2012-05-12 15:02:10 +00:00
|
|
|
/* Access routines used by filesel. */
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2021-06-23 09:51:11 +02:00
|
|
|
BlendHandle *BLO_blendhandle_from_file(const char *filepath, BlendFileReadReport *reports)
|
2004-09-05 13:43:51 +00:00
|
|
|
{
|
2008-12-19 00:50:21 +00:00
|
|
|
BlendHandle *bh;
|
2005-07-25 18:35:49 +00:00
|
|
|
|
2019-02-22 10:31:17 +11:00
|
|
|
bh = (BlendHandle *)blo_filedata_from_file(filepath, reports);
|
2008-12-19 00:50:21 +00:00
|
|
|
|
|
|
|
|
return bh;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2021-06-24 10:53:45 +02:00
|
|
|
BlendHandle *BLO_blendhandle_from_memory(const void *mem,
|
|
|
|
|
int memsize,
|
|
|
|
|
BlendFileReadReport *reports)
|
2010-08-28 02:07:55 +00:00
|
|
|
{
|
|
|
|
|
BlendHandle *bh;
|
|
|
|
|
|
2021-06-24 10:53:45 +02:00
|
|
|
bh = (BlendHandle *)blo_filedata_from_memory(mem, memsize, reports);
|
2010-08-28 02:07:55 +00:00
|
|
|
|
|
|
|
|
return bh;
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-17 17:06:07 +02:00
|
|
|
void BLO_blendhandle_print_sizes(BlendHandle *bh, void *fp)
|
2004-09-05 13:43:51 +00:00
|
|
|
{
|
2018-11-30 14:51:16 +11:00
|
|
|
FileData *fd = (FileData *)bh;
|
2002-10-12 11:37:38 +00:00
|
|
|
BHead *bhead;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
fprintf(fp, "[\n");
|
2019-02-22 10:31:17 +11:00
|
|
|
for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
|
2019-04-22 09:13:00 +10:00
|
|
|
if (bhead->code == ENDB) {
|
2002-10-12 11:37:38 +00:00
|
|
|
break;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2020-08-07 12:31:44 +02:00
|
|
|
|
2020-09-29 12:12:09 +02:00
|
|
|
const SDNA_Struct *struct_info = fd->filesdna->structs[bhead->SDNAnr];
|
|
|
|
|
const char *name = fd->filesdna->types[struct_info->type];
|
2020-08-07 12:31:44 +02:00
|
|
|
char buf[4];
|
|
|
|
|
|
|
|
|
|
buf[0] = (bhead->code >> 24) & 0xFF;
|
|
|
|
|
buf[1] = (bhead->code >> 16) & 0xFF;
|
|
|
|
|
buf[2] = (bhead->code >> 8) & 0xFF;
|
|
|
|
|
buf[3] = (bhead->code >> 0) & 0xFF;
|
|
|
|
|
|
|
|
|
|
buf[0] = buf[0] ? buf[0] : ' ';
|
|
|
|
|
buf[1] = buf[1] ? buf[1] : ' ';
|
|
|
|
|
buf[2] = buf[2] ? buf[2] : ' ';
|
|
|
|
|
buf[3] = buf[3] ? buf[3] : ' ';
|
|
|
|
|
|
|
|
|
|
fprintf(fp,
|
|
|
|
|
"['%.4s', '%s', %d, %ld ],\n",
|
|
|
|
|
buf,
|
|
|
|
|
name,
|
|
|
|
|
bhead->nr,
|
|
|
|
|
(long int)(bhead->len + sizeof(BHead)));
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
fprintf(fp, "]\n");
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-28 18:04:10 +01:00
|
|
|
LinkNode *BLO_blendhandle_get_datablock_names(BlendHandle *bh,
|
|
|
|
|
int ofblocktype,
|
|
|
|
|
const bool use_assets_only,
|
|
|
|
|
int *r_tot_names)
|
2004-09-05 13:43:51 +00:00
|
|
|
{
|
2018-11-30 14:51:16 +11:00
|
|
|
FileData *fd = (FileData *)bh;
|
2012-05-12 15:02:10 +00:00
|
|
|
LinkNode *names = NULL;
|
2002-10-12 11:37:38 +00:00
|
|
|
BHead *bhead;
|
2012-05-12 15:02:10 +00:00
|
|
|
int tot = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-22 10:31:17 +11:00
|
|
|
for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
|
2012-05-12 15:02:10 +00:00
|
|
|
if (bhead->code == ofblocktype) {
|
2019-02-22 10:31:17 +11:00
|
|
|
const char *idname = blo_bhead_id_name(fd, bhead);
|
2021-01-28 18:04:10 +01:00
|
|
|
if (use_assets_only && blo_bhead_id_asset_data_address(fd, bhead) == NULL) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-12-08 12:56:11 +01:00
|
|
|
BLI_linklist_prepend(&names, BLI_strdup(idname + 2));
|
2011-03-12 14:38:00 +00:00
|
|
|
tot++;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2019-04-22 09:13:00 +10:00
|
|
|
else if (bhead->code == ENDB) {
|
2002-10-12 11:37:38 +00:00
|
|
|
break;
|
2019-04-22 09:13:00 +10:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-01-28 18:04:10 +01:00
|
|
|
*r_tot_names = tot;
|
2002-10-12 11:37:38 +00:00
|
|
|
return names;
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-05 22:34:03 +11:00
|
|
|
LinkNode *BLO_blendhandle_get_datablock_info(BlendHandle *bh,
|
|
|
|
|
int ofblocktype,
|
2021-09-24 08:39:58 +02:00
|
|
|
const bool use_assets_only,
|
2021-02-05 22:34:03 +11:00
|
|
|
int *r_tot_info_items)
|
2020-12-11 18:15:25 +01:00
|
|
|
{
|
|
|
|
|
FileData *fd = (FileData *)bh;
|
|
|
|
|
LinkNode *infos = NULL;
|
|
|
|
|
BHead *bhead;
|
|
|
|
|
int tot = 0;
|
|
|
|
|
|
|
|
|
|
for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
|
2021-09-24 08:39:58 +02:00
|
|
|
if (bhead->code == ENDB) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-12-11 18:15:25 +01:00
|
|
|
if (bhead->code == ofblocktype) {
|
|
|
|
|
const char *name = blo_bhead_id_name(fd, bhead) + 2;
|
2021-09-24 08:39:58 +02:00
|
|
|
AssetMetaData *asset_meta_data = blo_bhead_id_asset_data_address(fd, bhead);
|
2020-12-11 18:15:25 +01:00
|
|
|
|
2021-09-24 08:39:58 +02:00
|
|
|
const bool is_asset = asset_meta_data != NULL;
|
|
|
|
|
const bool skip_datablock = use_assets_only && !is_asset;
|
|
|
|
|
if (skip_datablock) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
struct BLODataBlockInfo *info = MEM_mallocN(sizeof(*info), __func__);
|
2020-12-11 18:15:25 +01:00
|
|
|
|
|
|
|
|
/* Lastly, read asset data from the following blocks. */
|
2021-09-24 08:39:58 +02:00
|
|
|
if (asset_meta_data) {
|
|
|
|
|
bhead = blo_read_asset_data_block(fd, bhead, &asset_meta_data);
|
|
|
|
|
/* blo_read_asset_data_block() reads all DATA heads and already advances bhead to the
|
|
|
|
|
* next non-DATA one. Go back, so the loop doesn't skip the non-DATA head. */
|
2020-12-11 18:15:25 +01:00
|
|
|
bhead = blo_bhead_prev(fd, bhead);
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-24 08:39:58 +02:00
|
|
|
STRNCPY(info->name, name);
|
|
|
|
|
info->asset_data = asset_meta_data;
|
|
|
|
|
|
2020-12-11 18:15:25 +01:00
|
|
|
BLI_linklist_prepend(&infos, info);
|
|
|
|
|
tot++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-05 22:34:03 +11:00
|
|
|
*r_tot_info_items = tot;
|
2020-12-11 18:15:25 +01:00
|
|
|
return infos;
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-25 14:15:57 +02:00
|
|
|
/**
|
|
|
|
|
* Read the preview rects and store in `result`.
|
|
|
|
|
*
|
|
|
|
|
* `bhead` should point to the block that sourced the `preview_from_file`
|
|
|
|
|
* parameter.
|
|
|
|
|
* `bhead` parameter is consumed. The correct bhead pointing to the next bhead in the file after
|
|
|
|
|
* the preview rects is returned by this function.
|
|
|
|
|
* \param fd: The filedata to read the data from.
|
|
|
|
|
* \param bhead: should point to the block that sourced the `preview_from_file parameter`.
|
|
|
|
|
* bhead is consumed. the new bhead is returned by this function.
|
|
|
|
|
* \param result: the Preview Image where the preview rect will be stored.
|
|
|
|
|
* \param preview_from_file: The read PreviewImage where the bhead points to. The rects of this
|
|
|
|
|
* \return PreviewImage or NULL when no preview Images have been found. Caller owns the returned
|
|
|
|
|
*/
|
|
|
|
|
static BHead *blo_blendhandle_read_preview_rects(FileData *fd,
|
|
|
|
|
BHead *bhead,
|
|
|
|
|
PreviewImage *result,
|
|
|
|
|
const PreviewImage *preview_from_file)
|
|
|
|
|
{
|
|
|
|
|
for (int preview_index = 0; preview_index < NUM_ICON_SIZES; preview_index++) {
|
|
|
|
|
if (preview_from_file->rect[preview_index] && preview_from_file->w[preview_index] &&
|
|
|
|
|
preview_from_file->h[preview_index]) {
|
|
|
|
|
bhead = blo_bhead_next(fd, bhead);
|
|
|
|
|
BLI_assert((preview_from_file->w[preview_index] * preview_from_file->h[preview_index] *
|
|
|
|
|
sizeof(uint)) == bhead->len);
|
|
|
|
|
result->rect[preview_index] = BLO_library_read_struct(fd, bhead, "PreviewImage Icon Rect");
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* This should not be needed, but can happen in 'broken' .blend files,
|
|
|
|
|
* better handle this gracefully than crashing. */
|
|
|
|
|
BLI_assert(preview_from_file->rect[preview_index] == NULL &&
|
|
|
|
|
preview_from_file->w[preview_index] == 0 &&
|
|
|
|
|
preview_from_file->h[preview_index] == 0);
|
|
|
|
|
result->rect[preview_index] = NULL;
|
|
|
|
|
result->w[preview_index] = result->h[preview_index] = 0;
|
|
|
|
|
}
|
|
|
|
|
BKE_previewimg_finish(result, preview_index);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return bhead;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PreviewImage *BLO_blendhandle_get_preview_for_id(BlendHandle *bh,
|
|
|
|
|
int ofblocktype,
|
|
|
|
|
const char *name)
|
|
|
|
|
{
|
|
|
|
|
FileData *fd = (FileData *)bh;
|
|
|
|
|
bool looking = false;
|
|
|
|
|
const int sdna_preview_image = DNA_struct_find_nr(fd->filesdna, "PreviewImage");
|
|
|
|
|
|
|
|
|
|
for (BHead *bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
|
|
|
|
|
if (bhead->code == DATA) {
|
|
|
|
|
if (looking && bhead->SDNAnr == sdna_preview_image) {
|
|
|
|
|
PreviewImage *preview_from_file = BLO_library_read_struct(fd, bhead, "PreviewImage");
|
|
|
|
|
|
|
|
|
|
if (preview_from_file == NULL) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PreviewImage *result = MEM_dupallocN(preview_from_file);
|
|
|
|
|
bhead = blo_blendhandle_read_preview_rects(fd, bhead, result, preview_from_file);
|
|
|
|
|
MEM_freeN(preview_from_file);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (looking || bhead->code == ENDB) {
|
|
|
|
|
/* We were looking for a preview image, but didn't find any belonging to block. So it doesn't
|
|
|
|
|
* exist. */
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else if (bhead->code == ofblocktype) {
|
|
|
|
|
const char *idname = blo_bhead_id_name(fd, bhead);
|
|
|
|
|
if (STREQ(&idname[2], name)) {
|
|
|
|
|
looking = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-05 22:34:03 +11:00
|
|
|
LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *r_tot_prev)
|
2007-09-02 17:25:03 +00:00
|
|
|
{
|
2018-11-30 14:51:16 +11:00
|
|
|
FileData *fd = (FileData *)bh;
|
2012-05-12 15:02:10 +00:00
|
|
|
LinkNode *previews = NULL;
|
2007-09-02 17:25:03 +00:00
|
|
|
BHead *bhead;
|
2012-05-12 15:02:10 +00:00
|
|
|
int looking = 0;
|
|
|
|
|
PreviewImage *prv = NULL;
|
|
|
|
|
PreviewImage *new_prv = NULL;
|
|
|
|
|
int tot = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-22 10:31:17 +11:00
|
|
|
for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
|
2012-05-12 15:02:10 +00:00
|
|
|
if (bhead->code == ofblocktype) {
|
2019-02-22 10:31:17 +11:00
|
|
|
const char *idname = blo_bhead_id_name(fd, bhead);
|
2012-04-28 06:31:57 +00:00
|
|
|
switch (GS(idname)) {
|
2010-05-15 10:37:21 +00:00
|
|
|
case ID_MA: /* fall through */
|
|
|
|
|
case ID_TE: /* fall through */
|
|
|
|
|
case ID_IM: /* fall through */
|
|
|
|
|
case ID_WO: /* fall through */
|
|
|
|
|
case ID_LA: /* fall through */
|
2015-08-10 15:41:28 +02:00
|
|
|
case ID_OB: /* fall through */
|
|
|
|
|
case ID_GR: /* fall through */
|
|
|
|
|
case ID_SCE: /* fall through */
|
2021-02-05 11:28:34 +01:00
|
|
|
case ID_AC: /* fall through */
|
2021-11-06 16:43:26 +01:00
|
|
|
case ID_NT: /* fall through */
|
2010-05-15 10:37:21 +00:00
|
|
|
new_prv = MEM_callocN(sizeof(PreviewImage), "newpreview");
|
|
|
|
|
BLI_linklist_prepend(&previews, new_prv);
|
2011-04-24 14:45:49 +00:00
|
|
|
tot++;
|
2010-05-15 10:37:21 +00:00
|
|
|
looking = 1;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
2007-09-02 17:25:03 +00:00
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2012-05-12 15:02:10 +00:00
|
|
|
else if (bhead->code == DATA) {
|
2007-09-02 17:25:03 +00:00
|
|
|
if (looking) {
|
2008-10-31 23:50:02 +00:00
|
|
|
if (bhead->SDNAnr == DNA_struct_find_nr(fd->filesdna, "PreviewImage")) {
|
2012-10-21 05:46:41 +00:00
|
|
|
prv = BLO_library_read_struct(fd, bhead, "PreviewImage");
|
2020-12-14 13:21:58 +01:00
|
|
|
|
2011-05-18 19:42:30 +00:00
|
|
|
if (prv) {
|
|
|
|
|
memcpy(new_prv, prv, sizeof(PreviewImage));
|
2021-08-25 14:15:57 +02:00
|
|
|
bhead = blo_blendhandle_read_preview_rects(fd, bhead, new_prv, prv);
|
2011-05-18 19:42:30 +00:00
|
|
|
MEM_freeN(prv);
|
2007-09-02 17:25:03 +00:00
|
|
|
}
|
|
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2012-05-12 15:02:10 +00:00
|
|
|
else if (bhead->code == ENDB) {
|
2007-09-02 17:25:03 +00:00
|
|
|
break;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2007-09-02 17:25:03 +00:00
|
|
|
looking = 0;
|
|
|
|
|
new_prv = NULL;
|
|
|
|
|
prv = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-02-05 22:34:03 +11:00
|
|
|
*r_tot_prev = tot;
|
2007-09-02 17:25:03 +00:00
|
|
|
return previews;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-12 14:21:34 +02:00
|
|
|
LinkNode *BLO_blendhandle_get_linkable_groups(BlendHandle *bh)
|
2004-09-05 13:43:51 +00:00
|
|
|
{
|
2018-11-30 14:51:16 +11:00
|
|
|
FileData *fd = (FileData *)bh;
|
2013-08-25 20:03:45 +00:00
|
|
|
GSet *gathered = BLI_gset_ptr_new("linkable_groups gh");
|
2012-05-12 15:02:10 +00:00
|
|
|
LinkNode *names = NULL;
|
2002-10-12 11:37:38 +00:00
|
|
|
BHead *bhead;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-22 10:31:17 +11:00
|
|
|
for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
|
2012-05-12 15:02:10 +00:00
|
|
|
if (bhead->code == ENDB) {
|
2002-10-12 11:37:38 +00:00
|
|
|
break;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2020-08-07 12:31:44 +02:00
|
|
|
if (BKE_idtype_idcode_is_valid(bhead->code)) {
|
2020-03-19 19:37:00 +01:00
|
|
|
if (BKE_idtype_idcode_is_linkable(bhead->code)) {
|
|
|
|
|
const char *str = BKE_idtype_idcode_to_name(bhead->code);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-02-29 08:48:10 +11:00
|
|
|
if (BLI_gset_add(gathered, (void *)str)) {
|
2020-12-08 12:56:11 +01:00
|
|
|
BLI_linklist_prepend(&names, BLI_strdup(str));
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-08-25 20:03:45 +00:00
|
|
|
BLI_gset_free(gathered, NULL);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
return names;
|
2018-06-17 17:06:07 +02:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2011-09-28 05:53:40 +00:00
|
|
|
void BLO_blendhandle_close(BlendHandle *bh)
|
|
|
|
|
{
|
2018-11-30 14:51:16 +11:00
|
|
|
FileData *fd = (FileData *)bh;
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2019-02-22 10:31:17 +11:00
|
|
|
blo_filedata_free(fd);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2012-05-12 15:02:10 +00:00
|
|
|
/**********/
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2017-03-16 03:54:58 +11:00
|
|
|
BlendFileData *BLO_read_from_file(const char *filepath,
|
2018-11-22 14:57:41 +11:00
|
|
|
eBLOReadSkip skip_flags,
|
2021-06-23 09:51:11 +02:00
|
|
|
BlendFileReadReport *reports)
|
2004-09-05 13:43:51 +00:00
|
|
|
{
|
2002-10-12 11:37:38 +00:00
|
|
|
BlendFileData *bfd = NULL;
|
|
|
|
|
FileData *fd;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-06-22 19:11:06 +02:00
|
|
|
fd = blo_filedata_from_file(filepath, reports);
|
2002-10-12 11:37:38 +00:00
|
|
|
if (fd) {
|
2017-03-16 03:54:58 +11:00
|
|
|
fd->skip_flags = skip_flags;
|
2012-05-12 15:02:10 +00:00
|
|
|
bfd = blo_read_file_internal(fd, filepath);
|
2019-02-22 10:31:17 +11:00
|
|
|
blo_filedata_free(fd);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-10-21 05:46:41 +00:00
|
|
|
return bfd;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2017-03-16 03:54:58 +11:00
|
|
|
BlendFileData *BLO_read_from_memory(const void *mem,
|
|
|
|
|
int memsize,
|
2018-11-22 14:57:41 +11:00
|
|
|
eBLOReadSkip skip_flags,
|
|
|
|
|
ReportList *reports)
|
2004-09-05 13:43:51 +00:00
|
|
|
{
|
2002-10-12 11:37:38 +00:00
|
|
|
BlendFileData *bfd = NULL;
|
|
|
|
|
FileData *fd;
|
2021-06-24 10:53:45 +02:00
|
|
|
BlendFileReadReport bf_reports = {.reports = reports};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-06-24 10:53:45 +02:00
|
|
|
fd = blo_filedata_from_memory(mem, memsize, &bf_reports);
|
2002-10-12 11:37:38 +00:00
|
|
|
if (fd) {
|
2017-03-16 03:54:58 +11:00
|
|
|
fd->skip_flags = skip_flags;
|
2012-05-12 15:02:10 +00:00
|
|
|
bfd = blo_read_file_internal(fd, "");
|
2019-02-22 10:31:17 +11:00
|
|
|
blo_filedata_free(fd);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-10-21 05:46:41 +00:00
|
|
|
return bfd;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2017-03-16 03:54:58 +11:00
|
|
|
BlendFileData *BLO_read_from_memfile(Main *oldmain,
|
2022-05-17 11:38:05 +10:00
|
|
|
const char *filepath,
|
2017-03-16 03:54:58 +11:00
|
|
|
MemFile *memfile,
|
2020-03-17 12:29:36 +01:00
|
|
|
const struct BlendFileReadParams *params,
|
2018-11-22 14:57:41 +11:00
|
|
|
ReportList *reports)
|
2004-09-05 13:43:51 +00:00
|
|
|
{
|
|
|
|
|
BlendFileData *bfd = NULL;
|
|
|
|
|
FileData *fd;
|
Fix T34446: Make Local on linked mesh object: object gets removed if redo function is used.
Root of the issue is that we do not re-read lib data blocks and ID placholders (ID_ID bheads)
in undo context (in `blo_read_file_internal`), because `BLO_read_from_memfile` copies
lib datablocks and Main data directly from oldmain.
The idea being, linked data do not change from undo/redo.
This is valid as long as linked data was not changed by the undo step - but if some
was deleted or localized, it will be missing from oldmain, leading to data loss
(note that does not only concern objects, all linkable data types can be affected,
at least in theory).
This commit addresses that issue by carefully mixing reuse of needed data from oldmain,
and "normal" re-reading of missing one. Makes us swimming in some rather dark waters,
and gives a rather non-easy-to-follow code, but it seems to work quite well,
and only other solution would be to get rid of that optimization
(not re-reading all libs on undo/redo), which is not acceptable.
Also, thanks to @carlosdp for initial investigation of the issue.
Differential Revision: https://developer.blender.org/D1485
2015-10-12 12:15:05 +02:00
|
|
|
ListBase old_mainlist;
|
2021-06-24 10:53:45 +02:00
|
|
|
BlendFileReadReport bf_reports = {.reports = reports};
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2021-06-24 10:53:45 +02:00
|
|
|
fd = blo_filedata_from_memfile(memfile, params, &bf_reports);
|
2004-09-05 13:43:51 +00:00
|
|
|
if (fd) {
|
2020-03-17 12:29:36 +01:00
|
|
|
fd->skip_flags = params->skip_flags;
|
2022-05-17 11:38:05 +10:00
|
|
|
BLI_strncpy(fd->relabase, filepath, sizeof(fd->relabase));
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2008-12-19 16:36:15 +00:00
|
|
|
/* separate libraries from old main */
|
Fix T34446: Make Local on linked mesh object: object gets removed if redo function is used.
Root of the issue is that we do not re-read lib data blocks and ID placholders (ID_ID bheads)
in undo context (in `blo_read_file_internal`), because `BLO_read_from_memfile` copies
lib datablocks and Main data directly from oldmain.
The idea being, linked data do not change from undo/redo.
This is valid as long as linked data was not changed by the undo step - but if some
was deleted or localized, it will be missing from oldmain, leading to data loss
(note that does not only concern objects, all linkable data types can be affected,
at least in theory).
This commit addresses that issue by carefully mixing reuse of needed data from oldmain,
and "normal" re-reading of missing one. Makes us swimming in some rather dark waters,
and gives a rather non-easy-to-follow code, but it seems to work quite well,
and only other solution would be to get rid of that optimization
(not re-reading all libs on undo/redo), which is not acceptable.
Also, thanks to @carlosdp for initial investigation of the issue.
Differential Revision: https://developer.blender.org/D1485
2015-10-12 12:15:05 +02:00
|
|
|
blo_split_main(&old_mainlist, oldmain);
|
2006-11-25 13:07:28 +00:00
|
|
|
/* add the library pointers in oldmap lookup */
|
Fix T34446: Make Local on linked mesh object: object gets removed if redo function is used.
Root of the issue is that we do not re-read lib data blocks and ID placholders (ID_ID bheads)
in undo context (in `blo_read_file_internal`), because `BLO_read_from_memfile` copies
lib datablocks and Main data directly from oldmain.
The idea being, linked data do not change from undo/redo.
This is valid as long as linked data was not changed by the undo step - but if some
was deleted or localized, it will be missing from oldmain, leading to data loss
(note that does not only concern objects, all linkable data types can be affected,
at least in theory).
This commit addresses that issue by carefully mixing reuse of needed data from oldmain,
and "normal" re-reading of missing one. Makes us swimming in some rather dark waters,
and gives a rather non-easy-to-follow code, but it seems to work quite well,
and only other solution would be to get rid of that optimization
(not re-reading all libs on undo/redo), which is not acceptable.
Also, thanks to @carlosdp for initial investigation of the issue.
Differential Revision: https://developer.blender.org/D1485
2015-10-12 12:15:05 +02:00
|
|
|
blo_add_library_pointer_map(&old_mainlist, fd);
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2020-03-17 12:29:36 +01:00
|
|
|
if ((params->skip_flags & BLO_READ_SKIP_UNDO_OLD_MAIN) == 0) {
|
|
|
|
|
/* Build idmap of old main (we only care about local data here, so we can do that after
|
|
|
|
|
* split_main() call. */
|
|
|
|
|
blo_make_old_idmap_from_main(fd, old_mainlist.first);
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-13 12:25:56 +00:00
|
|
|
/* removed packed data from this trick - it's internal data that needs saves */
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2020-07-03 16:09:58 +02:00
|
|
|
/* Store all existing ID caches pointers into a mapping, to allow restoring them into newly
|
|
|
|
|
* read IDs whenever possible. */
|
2020-07-03 11:36:27 +02:00
|
|
|
blo_cache_storage_init(fd, oldmain);
|
|
|
|
|
|
2022-05-17 11:38:05 +10:00
|
|
|
bfd = blo_read_file_internal(fd, filepath);
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2020-07-03 16:09:58 +02:00
|
|
|
/* Ensure relinked caches are not freed together with their old IDs. */
|
2020-07-03 11:36:27 +02:00
|
|
|
blo_cache_storage_old_bmain_clear(fd, oldmain);
|
|
|
|
|
|
Fix T34446: Make Local on linked mesh object: object gets removed if redo function is used.
Root of the issue is that we do not re-read lib data blocks and ID placholders (ID_ID bheads)
in undo context (in `blo_read_file_internal`), because `BLO_read_from_memfile` copies
lib datablocks and Main data directly from oldmain.
The idea being, linked data do not change from undo/redo.
This is valid as long as linked data was not changed by the undo step - but if some
was deleted or localized, it will be missing from oldmain, leading to data loss
(note that does not only concern objects, all linkable data types can be affected,
at least in theory).
This commit addresses that issue by carefully mixing reuse of needed data from oldmain,
and "normal" re-reading of missing one. Makes us swimming in some rather dark waters,
and gives a rather non-easy-to-follow code, but it seems to work quite well,
and only other solution would be to get rid of that optimization
(not re-reading all libs on undo/redo), which is not acceptable.
Also, thanks to @carlosdp for initial investigation of the issue.
Differential Revision: https://developer.blender.org/D1485
2015-10-12 12:15:05 +02:00
|
|
|
/* Still in-use libraries have already been moved from oldmain to new mainlist,
|
|
|
|
|
* but oldmain itself shall *never* be 'transferred' to new mainlist! */
|
|
|
|
|
BLI_assert(old_mainlist.first == oldmain);
|
|
|
|
|
|
|
|
|
|
/* That way, libs (aka mains) we did not reuse in new undone/redone state
|
|
|
|
|
* will be cleared together with oldmain... */
|
|
|
|
|
blo_join_main(&old_mainlist);
|
|
|
|
|
|
2019-02-22 10:31:17 +11:00
|
|
|
blo_filedata_free(fd);
|
2004-09-05 13:43:51 +00:00
|
|
|
}
|
|
|
|
|
|
2012-10-21 05:46:41 +00:00
|
|
|
return bfd;
|
2004-09-05 13:43:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BLO_blendfiledata_free(BlendFileData *bfd)
|
|
|
|
|
{
|
2002-10-12 11:37:38 +00:00
|
|
|
if (bfd->main) {
|
2013-12-30 13:25:27 +11:00
|
|
|
BKE_main_free(bfd->main);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2018-06-17 17:06:07 +02:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if (bfd->user) {
|
|
|
|
|
MEM_freeN(bfd->user);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MEM_freeN(bfd);
|
|
|
|
|
}
|