Files
workinf_Blender_Wasm/blender-5.2.0/source/blender/blenloader/intern/readfile.hh
2026-08-12 04:47:48 -04:00

382 lines
14 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_enum_flags.hh"
#include "BLI_fileops.h"
#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"
namespace blender {
struct BlendFileData;
struct BlendfileLinkAppendContext;
struct BlendFileReadParams;
struct BlendFileReadReport;
struct BLOCacheStorage;
struct BHeadN;
struct BHeadSort;
struct DNA_ReconstructInfo;
struct IDNameLib_Map;
struct Key;
struct Main;
struct MemFile;
struct Object;
struct OldNewMap;
struct UserDef;
/**
* Store some critical information about the read blend-file.
*/
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,
/**
* The blend-file has IDs with invalid names (either using the 5.0+ new 'long names', or
* corrupted). I.e. their names have no null char in their first 66 bytes.
*/
FD_FLAGS_HAS_INVALID_ID_NAMES = 1 << 6,
};
ENUM_OPERATORS(eFileDataFlag)
/* 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. */
ListBaseT<BHeadN> bhead_list = {};
enum eFileDataFlag flags = eFileDataFlag(0);
bool is_eof = false;
BlenderHeader blender_header = {};
FileReader *file = nullptr;
std::optional<BLI_stat_t> file_stat;
/**
* 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;
/**
* Unlike the `fileversion` which is read from the header,
* this is initialized from #read_file_dna.
*/
int filesubversion = 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;
int id_flag_offset = 0;
int id_deep_hash_offset = 0;
/**
* Gives access to libraries' filepath and flag, useful for introspection of blendfiles'
* dependencies _without_ having to fully read them.
*/
int library_filepath_offset = 0;
int library_flag_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;
/** Used to keep track of already loaded packed IDs to avoid loading them multiple times. */
std::shared_ptr<Map<IDHash, ID *>> id_by_deep_hash;
/**
* 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<Map<StringRefNull, BHead *>> bhead_idname_map;
/**
* The root (main, local) Main.
* The Main that will own Library IDs.
*
* When reading libraries, this is typically _not_ the same Main as the one being populated from
* the content of this filedata, see #fd_bmain.
*/
Main *bmain = nullptr;
/** The existing root (main, local) Main, used for undo. */
Main *old_bmain = nullptr;
/**
* The main for the (local) data loaded from this filedata.
*
* This is the same as #bmain when opening a blend-file, but not when reading/loading from
* libraries blend-files.
*/
Main *fd_bmain = 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;
/**
* Set when reading a file from undo with incomplete preview, to trigger restart of preview jobs.
*/
bool need_preview_render_restart = false;
};
/**
* Split a single main into a vector of Mains, each containing only IDs from a given library.
*
* The vector is accessible in all of the split mains through the shared pointer
* #Main::split_mains.
*
* The first Main of the vector is the same as the given `main`, and contains local IDs.
*
* If `do_split_packed_ids` is `false`, packed linked IDs remain in the local (first) main as well.
*/
void blo_split_main(Main *bmain, bool do_split_packed_ids = true);
/**
* Join the set of split mains (found in given `main` #Main::split_mains vector shared pointer)
* back into that 'main' main.
*/
void blo_join_main(Main *bmain);
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 #IDNameLib_Map 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!
*
* Will return `nullptr` if the name is not valid (e.g. because it has no null-char terminator, if
* it was saved in a version of Blender with higher MAX_ID_NAME value).
*/
const char *blo_bhead_id_name(FileData *fd, const BHead *bhead);
/**
* Warning! It's the caller's responsibility to ensure that the given bhead **is** an ID one!
*
* Returns the ID flag value (or `0` if the blendfile is too old and the offset of the ID::flag
* member could not be computed).
*/
short blo_bhead_id_flag(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);
/**
* Return the stored filepath (may be relative) of a library ID.
*
* Warning! Caller's responsibility to ensure that the given bhead **is** a Library ID one!
*/
const char *blo_bhead_library_filepath(const FileData *fd, const BHead *bhead);
/**
* Return the stored flags of a library ID.
*
* Warning! Caller's responsibility to ensure that the given bhead **is** a Library ID one!
*/
LibraryFlag blo_bhead_library_flag(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 blo_do_versions_500(FileData *fd, Library *lib, Main *bmain);
void blo_do_versions_510(FileData *fd, Library *lib, Main *bmain);
void blo_do_versions_520(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_linking_500(FileData *fd, Main *bmain);
void do_versions_after_linking_510(FileData *fd, Main *bmain);
void do_versions_after_linking_520(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);
} // namespace blender