Files
test/source/blender/blenloader/intern/readfile.hh

284 lines
10 KiB
C++

/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup blenloader
* blenloader readfile private function prototypes.
*/
#pragma once
#include <cstdio> /* IWYU pragma: keep. Include header using off_t before poisoning it below. */
#include <optional>
#ifdef WIN32
# include "BLI_winstuff.h"
#endif
#include "BLI_filereader.h"
#include "BLI_map.hh"
#include "DNA_sdna_types.h"
#include "DNA_space_types.h"
#include "BLO_core_bhead.hh"
#include "BLO_core_blend_header.hh"
#include "BLO_readfile.hh"
struct BlendFileData;
struct BlendfileLinkAppendContext;
struct BlendFileReadParams;
struct BlendFileReadReport;
struct BLOCacheStorage;
struct BHeadSort;
struct DNA_ReconstructInfo;
struct IDNameLib_Map;
struct Key;
struct Main;
struct MemFile;
struct Object;
struct OldNewMap;
struct UserDef;
enum eFileDataFlag {
FD_FLAGS_SWITCH_ENDIAN = 1 << 0,
FD_FLAGS_FILE_POINTSIZE_IS_4 = 1 << 1,
FD_FLAGS_POINTSIZE_DIFFERS = 1 << 2,
FD_FLAGS_FILE_OK = 1 << 3,
FD_FLAGS_IS_MEMFILE = 1 << 4,
/**
* The Blender file is not compatible with current code, but is still likely a blender file
* 'from the future'. Improves report to the user.
*/
FD_FLAGS_FILE_FUTURE = 1 << 5,
};
ENUM_OPERATORS(eFileDataFlag, FD_FLAGS_IS_MEMFILE)
/* Disallow since it's 32bit on ms-windows. */
#ifdef __GNUC__
# pragma GCC poison off_t
#endif
/**
* General data used during a blend-file reading.
*
* Note that this data (and its accesses) are absolutely not thread-safe currently. It should never
* be accessed concurrently.
*/
struct FileData {
/** Linked list of BHeadN's. */
ListBase bhead_list = {};
enum eFileDataFlag flags = eFileDataFlag(0);
bool is_eof = false;
BlenderHeader blender_header = {};
FileReader *file = nullptr;
/**
* Whether we are undoing (< 0) or redoing (> 0), used to choose which 'unchanged' flag to use
* to detect unchanged data from memfile.
* #eUndoStepDir.
*/
int undo_direction = 0;
/** Used for relative paths handling.
*
* Typically the actual filepath of the read blend-file, except when recovering
* save-on-exit/autosave files. In the latter case, it will be the path of the file that
* generated the auto-saved one being recovered.
*
* NOTE: Currently expected to be the same path as #BlendFileData.filepath. */
char relabase[FILE_MAX] = {};
/** General reading variables. */
SDNA *filesdna = nullptr;
const SDNA *memsdna = nullptr;
/** Array of #eSDNA_StructCompare. */
const char *compflags = nullptr;
DNA_ReconstructInfo *reconstruct_info = nullptr;
int fileversion = 0;
/** Used to retrieve ID names from (bhead+1). */
int id_name_offset = 0;
/** Used to retrieve asset data from (bhead+1). NOTE: This may not be available in old files,
* will be -1 then! */
int id_asset_data_offset = 0;
/** For do_versions patching. */
int globalf = 0;
int fileflags = 0;
/** Optionally skip some data-blocks when they're not needed. */
eBLOReadSkip skip_flags = BLO_READ_SKIP_NONE;
/**
* Tag to apply to all loaded ID data-blocks.
*
* \note This is initialized from #LibraryLink_Params.id_tag_extra since passing it as an
* argument would need an additional argument to be passed around when expanding library data.
*/
int id_tag_extra = 0;
OldNewMap *datamap = nullptr;
OldNewMap *globmap = nullptr;
/**
* Store mapping from old ID pointers (the values they have in the .blend file) to new ones,
* typically from value in `bhead->old` to address in memory where the ID was read.
* Used during library-linking process (see #lib_link_all).
*/
OldNewMap *libmap = nullptr;
BLOCacheStorage *cache_storage = nullptr;
BHeadSort *bheadmap = nullptr;
int tot_bheadmap = 0;
std::optional<blender::Map<blender::StringRefNull, BHead *>> bhead_idname_map;
ListBase *mainlist = nullptr;
/** Used for undo. */
ListBase *old_mainlist = nullptr;
/**
* IDMap using UID's as keys of all the old IDs in the old bmain. Used during undo to find a
* matching old data when reading a new ID. */
IDNameLib_Map *old_idmap_uid = nullptr;
/**
* IDMap using uids as keys of the IDs read (or moved) in the new main(s).
*
* Used during undo to ensure that the ID pointers from the 'no undo' IDs remain valid (these
* IDs are re-used from old main even if their content is not the same as in the memfile undo
* step, so they could point e.g. to an ID that does not exist in the newly read undo step).
*
* Also used to find current valid pointers (or none) of these 'no undo' IDs existing in
* read memfile. */
IDNameLib_Map *new_idmap_uid = nullptr;
BlendFileReadReport *reports = nullptr;
/** Opaque handle to the storage system used for non-static allocation strings. */
void *storage_handle = nullptr;
};
/***/
void blo_join_main(ListBase *mainlist);
void blo_split_main(ListBase *mainlist, Main *main);
BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath) ATTR_NONNULL(1, 2);
/**
* On each new library added, it now checks for the current #FileData and expands relativeness
*
* cannot be called with relative paths anymore!
*/
FileData *blo_filedata_from_file(const char *filepath, BlendFileReadReport *reports);
FileData *blo_filedata_from_memory(const void *mem, int memsize, BlendFileReadReport *reports);
FileData *blo_filedata_from_memfile(MemFile *memfile,
const BlendFileReadParams *params,
BlendFileReadReport *reports);
/**
* Build a #GSet of old main (we only care about local data here,
* so we can do that after #blo_split_main() call.
*/
void blo_make_old_idmap_from_main(FileData *fd, Main *bmain) ATTR_NONNULL(1, 2);
BHead *blo_read_asset_data_block(FileData *fd, BHead *bhead, AssetMetaData **r_asset_data)
ATTR_NONNULL(1, 2);
void blo_cache_storage_init(FileData *fd, Main *bmain) ATTR_NONNULL(1, 2);
void blo_cache_storage_old_bmain_clear(FileData *fd, Main *bmain_old) ATTR_NONNULL(1, 2);
void blo_cache_storage_end(FileData *fd) ATTR_NONNULL(1);
void blo_filedata_free(FileData *fd) ATTR_NONNULL(1);
BHead *blo_bhead_first(FileData *fd) ATTR_NONNULL(1);
BHead *blo_bhead_next(FileData *fd, BHead *thisblock) ATTR_NONNULL(1);
BHead *blo_bhead_prev(FileData *fd, BHead *thisblock) ATTR_NONNULL(1, 2);
/**
* Warning! Caller's responsibility to ensure given bhead **is** an ID one!
*/
const char *blo_bhead_id_name(const FileData *fd, const BHead *bhead);
/**
* Warning! Caller's responsibility to ensure given bhead **is** an ID one!
*/
AssetMetaData *blo_bhead_id_asset_data_address(const FileData *fd, const BHead *bhead);
/* do versions stuff */
/**
* Manipulates SDNA before calling #DNA_struct_get_compareflags,
* allowing us to rename structs and struct members.
*
* - This means older versions of Blender won't have access to this data **USE WITH CARE**.
* - These changes are applied on file load (run-time), similar to versioning for compatibility.
*
* \attention ONLY USE THIS KIND OF VERSIONING WHEN `dna_rename_defs.h` ISN'T SUFFICIENT.
*/
void blo_do_versions_dna(SDNA *sdna, int versionfile, int subversionfile);
void blo_do_versions_oldnewmap_insert(OldNewMap *onm, const void *oldaddr, void *newaddr, int nr);
/**
* Only library data.
*/
void *blo_do_versions_newlibadr(FileData *fd,
ID *self_id,
const bool is_linked_only,
const void *adr);
/**
* \note this version patch is intended for versions < 2.52.2,
* but was initially introduced in 2.27 already.
*/
void blo_do_version_old_trackto_to_constraints(Object *ob);
void blo_do_versions_key_uidgen(Key *key);
/**
* Patching #UserDef struct and Themes.
*/
void blo_do_versions_userdef(UserDef *userdef);
void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain);
void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain);
void blo_do_versions_260(FileData *fd, Library *lib, Main *bmain);
void blo_do_versions_270(FileData *fd, Library *lib, Main *bmain);
void blo_do_versions_280(FileData *fd, Library *lib, Main *bmain);
void blo_do_versions_290(FileData *fd, Library *lib, Main *bmain);
void blo_do_versions_300(FileData *fd, Library *lib, Main *bmain);
void blo_do_versions_400(FileData *fd, Library *lib, Main *bmain);
void blo_do_versions_410(FileData *fd, Library *lib, Main *bmain);
void blo_do_versions_420(FileData *fd, Library *lib, Main *bmain);
void blo_do_versions_430(FileData *fd, Library *lib, Main *bmain);
void blo_do_versions_440(FileData *fd, Library *lib, Main *bmain);
void blo_do_versions_450(FileData *fd, Library *lib, Main *bmain);
void do_versions_after_linking_250(Main *bmain);
void do_versions_after_linking_260(Main *bmain);
void do_versions_after_linking_270(Main *bmain);
void do_versions_after_linking_280(FileData *fd, Main *bmain);
void do_versions_after_linking_290(FileData *fd, Main *bmain);
void do_versions_after_linking_300(FileData *fd, Main *bmain);
void do_versions_after_linking_400(FileData *fd, Main *bmain);
void do_versions_after_linking_410(FileData *fd, Main *bmain);
void do_versions_after_linking_420(FileData *fd, Main *bmain);
void do_versions_after_linking_430(FileData *fd, Main *bmain);
void do_versions_after_linking_440(FileData *fd, Main *bmain);
void do_versions_after_linking_450(FileData *fd, Main *bmain);
void do_versions_after_setup(Main *new_bmain,
BlendfileLinkAppendContext *lapp_context,
BlendFileReadReport *reports);
/**
* Direct data-blocks with global linking.
*
* \note This is rather unfortunate to have to expose this here,
* but better use that nasty hack in do_version than readfile itself.
*/
void *blo_read_get_new_globaldata_address(FileData *fd, const void *adr) ATTR_NONNULL(1);
/* Mark the Main data as invalid (.blend file reading should be aborted ASAP, and the already read
* data should be discarded). Also add an error report to `fd` including given `message`. */
void blo_readfile_invalidate(FileData *fd, Main *bmain, const char *message) ATTR_NONNULL(1, 2, 3);