80#include <fmt/format.h>
87#define DNA_DEPRECATED_ALLOW
143#define U (*((const UserDef *)&U))
149#define GENERATE_DEBUG_BLEND_FILE 0
150#define DEBUG_BLEND_FILE_SUFFIX ".debug.txt"
155#define MEM_BUFFER_SIZE MEM_SIZE_OPTIMAL(1 << 17)
156#define MEM_CHUNK_SIZE MEM_SIZE_OPTIMAL(1 << 15)
158#define ZSTD_BUFFER_SIZE (1 << 21)
159#define ZSTD_CHUNK_SIZE (1 << 20)
161#define ZSTD_COMPRESSION_LEVEL 3
181 virtual bool open(
const char *filepath) = 0;
183 virtual bool write(
const void *buf,
size_t buf_len) = 0;
191 bool open(
const char *filepath)
override;
192 bool close()
override;
193 bool write(
const void *buf,
size_t buf_len)
override;
214 return (
::close(file_handle) != -1);
218 return ::write(file_handle, buf, buf_len) == buf_len;
233 bool write_error =
false;
238 bool open(
const char *filepath)
override;
239 bool close()
override;
240 bool write(
const void *buf,
size_t buf_len)
override;
243 struct ZstdWriteBlockTask;
244 void write_task(ZstdWriteBlockTask *task);
245 void write_u32_le(uint32_t val);
246 void write_seekable_frames();
259 task->
ww->write_task(task);
264void ZstdWriteWrap::write_task(ZstdWriteBlockTask *task)
266 size_t out_buf_len = ZSTD_compressBound(task->size);
267 void *out_buf =
MEM_mallocN(out_buf_len,
"Zstd out buffer");
268 size_t out_size = ZSTD_compress(
275 while (next_frame != task->frame_number) {
279 if (ZSTD_isError(out_size)) {
283 if (base_wrap.write(out_buf, out_size)) {
304 if (!base_wrap.open(filepath)) {
317void ZstdWriteWrap::write_u32_le(uint32_t val)
322 base_wrap.
write(&val,
sizeof(uint32_t));
333void ZstdWriteWrap::write_seekable_frames()
336 write_u32_le(0x184D2A5E);
342 const uint32_t frame_size = num_frames * 8 + 9;
343 write_u32_le(frame_size);
347 write_u32_le(frame->compressed_size);
348 write_u32_le(frame->uncompressed_size);
352 write_u32_le(num_frames);
353 const char flags = 0;
354 base_wrap.write(&flags, 1);
355 write_u32_le(0x8F92EAB1);
366 write_seekable_frames();
369 return base_wrap.close() && !write_error;
380 memcpy(task->
data, buf, buf_len);
381 task->
size = buf_len;
430#ifdef USE_WRITE_DATA_LEN
517 WriteData *wd = MEM_new<WriteData>(__func__);
525 if ((ww ==
nullptr) || (ww->
use_buf)) {
546 if (memlen > INT_MAX) {
560 if (!wd->
ww->
write(mem, memlen)) {
608#ifdef USE_WRITE_DATA_LEN
609 wd->write_len +=
len;
627 adr = (
const char *)adr + writelen;
657 if (current !=
nullptr) {
716 return uint64_t(
id.session_uid) << 20;
724 const uint64_t lib_hash = XXH3_64bits(
id.
lib->id.name, strlen(
id.
lib->id.name));
741 "The only IDs with non-null deep-hash data should be packed linked ones");
743 "Embedded IDs should always have a null deep-hash data");
755 const MemFileChunk *prev_memchunk = curr_memchunk !=
nullptr ?
759 (prev_memchunk !=
nullptr &&
818 "Same identifier (old address) used several times for a same ID, skipping this "
819 "block to avoid critical corruption of the Blender file.");
828 if constexpr (
sizeof(
void *) == 4) {
832 bh.
old = uint32_t(uintptr_t(bhead.
old));
843 mywrite(wd, &bhead,
sizeof(bhead));
856 if (bhead.
len > std::numeric_limits<
decltype(bh.
len)>
::max()) {
857 CLOG_ERROR(&
LOG,
"Written .blend file is corrupt, because a memory block is too large.");
871 if (stable_id == 0) {
873 stable_id = (1 << 4);
887 hint = XXH3_64bits(&hint,
sizeof(
uint64_t));
917 if (address ==
nullptr) {
940 if (adr ==
nullptr ||
data ==
nullptr || nr == 0) {
953 CLOG_ERROR(&
LOG,
"Cannot write chunks bigger than INT_MAX.");
963 const bool can_write_raw_runtime_data = struct_info.
pointers.is_empty();
966 const void *data_to_write;
967 if (can_write_raw_runtime_data) {
969 data_to_write =
data;
972 void *buffer = buffer_owner.
buffer();
973 data_to_write = buffer;
974 memcpy(buffer,
data, len_in_bytes);
980 const void **p_ptr =
reinterpret_cast<const void **
>(
POINTER_OFFSET(buffer, offset));
992 bh.
len = len_in_bytes;
1000 *wd->
sdna, struct_nr, data_to_write, address_id, nr, *wd->
debug_dst);
1008 WriteData *wd,
const int filecode,
const int struct_nr,
const int64_t nr,
const void *adr)
1015 const void *address_id,
1018 fmt::memory_buffer buf;
1019 fmt::appender dst{buf};
1021 fmt::format_to(dst,
"<Raw Data> at {} ({} bytes)\n", address_id,
len);
1023 constexpr int bytes_per_row = 8;
1024 const int len_digits = std::to_string(std::max<size_t>(0,
len - 1)).size();
1026 for (
size_t i = 0;
i <
len;
i++) {
1027 if (
i % bytes_per_row == 0) {
1028 fmt::format_to(dst,
" {:{}}: ",
i, len_digits);
1030 fmt::format_to(dst,
"{:02x} ",
reinterpret_cast<const uint8_t *
>(
data)[
i]);
1031 if (
i % bytes_per_row == bytes_per_row - 1) {
1032 fmt::format_to(dst,
"\n");
1035 if (
len % bytes_per_row != 0) {
1036 fmt::format_to(dst,
"\n");
1046 WriteData *wd,
const int filecode,
const void *
data,
const size_t len,
const void *adr)
1048 if (
data ==
nullptr ||
len == 0) {
1068 bh.
old = address_id;
1092 const int struct_nr,
1104static void writelist_id(
WriteData *wd,
const int filecode,
const char *structname,
const ListBase *lb)
1110 if (struct_nr == -1) {
1111 printf(
"error: cannot find SDNA code <%s>\n", structname);
1123#define writestruct_at_address(wd, filecode, struct_id, nr, adr, data) \
1124 writestruct_at_address_nr( \
1125 wd, filecode, blender::dna::sdna_struct_id_get<struct_id>(), nr, adr, data)
1127#define writestruct(wd, filecode, struct_id, nr, adr) \
1128 writestruct_nr(wd, filecode, blender::dna::sdna_struct_id_get<struct_id>(), nr, adr)
1143 const bool use_active_win,
1156 if (use_active_win) {
1165 if (window ==
nullptr) {
1175 *r_scene = (window) ? window->
scene :
nullptr;
1195 Scene *curscene =
nullptr;
1204 data.sfra = sce->r.sfra;
1205 data.efra = sce->r.efra;
1206 memset(
data.scene_name, 0,
sizeof(
data.scene_name));
1236 if (kmdi->remove_item) {
1239 if (kmdi->add_item) {
1354 linked_ids_by_library.
add(id->
lib,
id);
1360 Library &library = *library_ptr;
1365 for (
ID *
id : ids) {
1371 ids_used_from_library.
append(
id);
1375 ids_used_from_library.
append(
id);
1379 ids_used_from_library.
append(
id);
1384 bool should_write_library =
false;
1386 should_write_library =
true;
1388 else if (!library.
runtime->archived_libraries.is_empty()) {
1395 should_write_library =
true;
1400 should_write_library =
true;
1403 should_write_library = !ids_used_from_library.
is_empty();
1406 if (!should_write_library) {
1415 for (
ID *
id : ids_used_from_library) {
1422 "Data-block '%s' from lib '%s' is not linkable, but is flagged as "
1425 library.
runtime->filepath_abs);
1435#ifdef WITH_BUILDINFO
1455 memset(fg.
_pad, 0,
sizeof(fg.
_pad));
1482 memcpy(fg.
subvstr, subvstr, 4);
1487#ifdef WITH_BUILDINFO
1521 ID *temp_id =
static_cast<ID *
>(buffer_.buffer());
1527 id.recalc_up_to_undo_push =
id.recalc_after_undo_push;
1528 id.recalc_after_undo_push = 0;
1533 if (is_placeholder) {
1537 temp_id->
lib =
id.lib;
1539 temp_id->
flag =
id.flag;
1565 temp_id->
prev =
nullptr;
1566 temp_id->
next =
nullptr;
1570 temp_id->
newid =
nullptr;
1632 std::stringstream ss;
1634 ss << header_size_in_bytes;
1640 const std::string header = ss.str();
1641 BLI_assert(header.size() == header_size_in_bytes);
1645 const char pointer_size_char =
sizeof(
void *) == 8 ?
'-' :
'_';
1646 const char endian_char =
'v';
1649 std::stringstream ss;
1651 ss << pointer_size_char;
1654 const std::string header = ss.str();
1662 mywrite(wd, header.data(), header.size());
1711 Key *shape_key =
reinterpret_cast<Key *
>(id);
1715 if (shape_key->
from ==
nullptr || shape_key->
from->
us == 0) {
1727 local_ids_to_write.
append(
id);
1730 return local_ids_to_write;
1766 const int write_flags,
1767 const bool use_userdef,
1769 std::ostream *debug_dst)
1838 for (
ID *
id : local_ids_to_write) {
1847 for (
ID *
id : local_ids_to_write) {
1855 for (
ID *
id : local_ids_to_write) {
1891 int version_number =
min_ii(99,
U.versions);
1893 if (version_number == 0) {
1897 if (strlen(filepath) < 2) {
1902 while (version_number > 1) {
1903 SNPRINTF(filepath_tmp1,
"%s%d", filepath, version_number - 1);
1905 SNPRINTF(filepath_tmp2,
"%s%d", filepath, version_number);
1917 SNPRINTF(filepath_tmp1,
"%s%d", filepath, version_number);
1936 reports,
RPT_DEBUG,
"Checking validity of current .blend file *BEFORE* save to disk");
1943 "Critical data corruption: Conflicts and/or otherwise invalid data-blocks names "
1944 "(see console for details)");
1960 reports,
RPT_DEBUG,
"Checking validity of current .blend file *BEFORE* save to disk");
1966 const char *filepath,
1967 const int write_flags,
1978 const bool use_save_versions =
params->use_save_versions;
1979 const bool use_save_as_copy =
params->use_save_as_copy;
1980 const bool use_userdef =
params->use_userdef;
1982 const bool relbase_valid = (mainvar->
filepath[0] !=
'\0');
1988 BKE_reportf(reports,
RPT_ERROR,
"Cannot save normal file (%s) as asset system file", tempname);
1993 void *path_list_backup =
nullptr;
2000 SNPRINTF(tempname,
"%s@", filepath);
2002 if (ww.
open(tempname) ==
false) {
2004 reports,
RPT_ERROR,
"Cannot open file %s for writing: %s", tempname, strerror(errno));
2010 if (relbase_valid ==
false) {
2019 if (relbase_valid ==
false) {
2029 if (relbase_valid) {
2041 if (relbase_valid && (
BLI_path_cmp(dir_dst, dir_src) == 0)) {
2047 if (relbase_valid ==
false) {
2058 char mainvar_filepath_orig[
FILE_MAX];
2067 switch (remap_mode) {
2091#if GENERATE_DEBUG_BLEND_FILE
2094 std::ostream *debug_dst = &debug_dst_file;
2096 std::ostream *debug_dst =
nullptr;
2101 mainvar, &ww,
nullptr,
nullptr, write_flags, use_userdef, thumb, debug_dst);
2119 if (use_save_versions) {
2134 STRNCPY(
G.filepath_last_blend, filepath);
2146 const char *filepath,
2147 const int write_flags,
2163 bool use_userdef =
false;
2166 mainvar,
nullptr, compare, current, write_flags, use_userdef,
nullptr,
nullptr);
2186 const char *struct_name,
2188 const void *data_ptr)
2204 const int struct_id,
2205 const void *address,
2206 const void *data_ptr)
2214 const int struct_id,
2215 const void *address,
2216 const void *data_ptr)
2222 const int struct_id,
2224 const void *data_ptr)
2230 const int struct_id,
2232 const void *address,
2233 const void *data_ptr)
2254 const int struct_id,
2255 const void *id_address,
2312 reinterpret_cast<const void *
const *
>(data_ptr),
num);
2327 if (data_ptr !=
nullptr) {
2349 const size_t approximate_size_in_bytes,
2353 if (
data ==
nullptr) {
2362 if (sharing_info !=
nullptr) {
2364 memfile.
shared_storage = MEM_new<MemFileSharedStorage>(__func__);
2376 if (sharing_info !=
nullptr) {
void BKE_asset_catalog_path_list_blend_write(BlendWriter *writer, const ListBase &catalog_path_list)
#define BLENDER_FILE_SUBVERSION
#define BLENDER_FILE_MIN_VERSION
#define BLENDER_FILE_VERSION
#define BLENDER_FILE_MIN_SUBVERSION
void BKE_bpath_relative_convert(Main *bmain, const char *basedir, ReportList *reports, BPathSummary *r_summary=nullptr)
void * BKE_bpath_list_backup(Main *bmain, eBPathForeachFlag flag)
void BKE_bpath_absolute_convert(Main *bmain, const char *basedir, ReportList *reports, BPathSummary *r_summary=nullptr)
void BKE_bpath_list_restore(Main *bmain, eBPathForeachFlag flag, void *path_list_handle)
void BKE_bpath_relative_rebase(Main *bmain, const char *basedir_src, const char *basedir_dst, ReportList *reports, BPathSummary *r_summary=nullptr)
@ BKE_BPATH_FOREACH_PATH_SKIP_LINKED
@ BKE_BPATH_FOREACH_PATH_SKIP_MULTIFILE
void BKE_bpath_list_free(void *path_list_handle)
#define G_FILE_FLAG_ALL_RUNTIME
void IDP_BlendWrite(BlendWriter *writer, const IDProperty *prop)
const IDTypeInfo * BKE_idtype_get_info_from_id(const ID *id)
@ IDTYPE_FLAGS_NEVER_UNUSED
bool BKE_idtype_idcode_is_linkable(short idcode)
ViewLayer * BKE_view_layer_find(const Scene *scene, const char *layer_name)
void id_lib_extern(ID *id)
#define MAIN_ID_SESSION_UID_UNSET
void id_lib_indirect_weak_link(ID *id)
void BKE_main_id_refcount_recompute(Main *bmain, bool do_linked_only)
void BKE_lib_override_library_operations_create(Main *bmain, ID *local, int *r_report_flags)
LibraryForeachIDCallbackFlag
@ IDWALK_CB_WRITEFILE_IGNORE
@ IDWALK_CB_DIRECT_WEAK_LINK
@ IDWALK_CB_INDIRECT_USAGE
void BKE_library_foreach_ID_link(Main *bmain, ID *id, blender::FunctionRef< LibraryIDLinkCallback > callback, void *user_data, LibraryForeachIDFlag flag)
#define FOREACH_MAIN_ID_END
#define FOREACH_MAIN_ID_BEGIN(_bmain, _id)
bool BKE_main_namemap_validate_and_fix(Main &bmain)
void BKE_preferences_extension_repo_write_data(struct BlendWriter *writer, const bUserExtensionRepo *repo)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
bScreen * BKE_workspace_active_screen_get(const WorkSpaceInstanceHook *hook) GETTER_ATTRS
#define BLI_assert_unreachable()
#define BLI_STATIC_ASSERT(a, msg)
#define BLI_assert_msg(a, msg)
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
int BLI_rename_overwrite(const char *from, const char *to) ATTR_NONNULL()
int BLI_open(const char *filepath, int oflag, int pmode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
File and directory operations.
#define LISTBASE_FOREACH(type, var, list)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
int BLI_listbase_count(const ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
void copy_m3_m3(float m1[3][3], const float m2[3][3])
ATTR_WARN_UNUSED_RESULT const size_t num
int BLI_path_normalize(char *path) ATTR_NONNULL(1)
bool BLI_path_is_abs_from_cwd(const char *path) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
bool BLI_path_is_rel(const char *path) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
void void BLI_path_split_dir_part(const char *filepath, char *dir, size_t dir_maxncpy) ATTR_NONNULL(1
#define SNPRINTF(dst, format,...)
char * STRNCPY(char(&dst)[N], const char *src)
void BLI_condition_notify_all(ThreadCondition *cond)
void BLI_mutex_end(ThreadMutex *mutex)
void BLI_threadpool_remove(struct ListBase *threadbase, void *callerdata)
void BLI_condition_wait(ThreadCondition *cond, ThreadMutex *mutex)
void BLI_threadpool_init(struct ListBase *threadbase, void *(*do_thread)(void *), int tot)
void BLI_mutex_init(ThreadMutex *mutex)
pthread_cond_t ThreadCondition
void BLI_condition_end(ThreadCondition *cond)
int BLI_system_thread_count(void)
void BLI_threadpool_end(struct ListBase *threadbase)
void BLI_condition_init(ThreadCondition *cond)
void BLI_mutex_lock(ThreadMutex *mutex)
void BLI_mutex_unlock(ThreadMutex *mutex)
int BLI_available_threads(struct ListBase *threadbase)
void BLI_threadpool_insert(struct ListBase *threadbase, void *callerdata)
pthread_mutex_t ThreadMutex
#define UNUSED_VARS_NDEBUG(...)
#define POINTER_OFFSET(v, ofs)
Compatibility-like things for windows.
Utilities ensuring .blend file (i.e. Main) is in valid state during write and/or read process.
bool BLO_main_validate_libraries(Main *bmain, ReportList *reports)
bool BLO_main_validate_shapekeys(Main *bmain, ReportList *reports)
#define BLO_write_struct(writer, struct_name, data_ptr)
bool BLO_write_is_undo(BlendWriter *writer)
external readfile function prototypes.
#define BLEN_THUMB_MEMSIZE_FILE(_x, _y)
void BLO_memfile_chunk_add(MemFileWriteData *mem_data, const char *buf, size_t size)
void BLO_memfile_write_init(MemFileWriteData *mem_data, MemFile *written_memfile, MemFile *reference_memfile)
void BLO_memfile_write_finalize(MemFileWriteData *mem_data)
external writefile.cc function prototypes.
@ BLO_WRITE_PATH_REMAP_NONE
@ BLO_WRITE_PATH_REMAP_RELATIVE_ALL
@ BLO_WRITE_PATH_REMAP_ABSOLUTE
@ BLO_WRITE_PATH_REMAP_RELATIVE
#define CLOG_ERROR(clg_ref,...)
#define ID_IS_OVERRIDE_LIBRARY_VIRTUAL(_id)
#define ID_IS_PACKED(_id)
@ ID_TAG_NO_USER_REFCOUNT
#define ID_IS_OVERRIDE_LIBRARY_REAL(_id)
#define ID_IS_LINKED(_id)
#define ID_TAG_KEEP_ON_UNDO
@ ID_FLAG_INDIRECT_WEAK_LINK
@ LIBRARY_FLAG_IS_ARCHIVE
#define ID_LINK_PLACEHOLDER
blenloader genfile private function prototypes
const struct SDNA * DNA_sdna_current_get(void)
int DNA_struct_find_with_alias(const struct SDNA *sdna, const char *str)
int DNA_struct_size(const struct SDNA *sdna, int struct_index)
#define SDNA_RAW_DATA_STRUCT_INDEX
#define USER_DEVELOPER_TOOL_TEST(userdef, member)
@ USER_MENU_TYPE_OPERATOR
Read Guarded memory(de)allocation.
BMesh const char void * data
ulong build_commit_timestamp
unsigned long long int uint64_t
bool add(const Key &key, const Value &value)
Value lookup_default(const Key &key, const Value &default_value) const
Value & lookup_or_add_cb(const Key &key, const CreateValueF &create_value)
bool contains(const Key &key) const
bool write(const void *buf, size_t buf_len) override
bool open(const char *filepath) override
virtual bool open(const char *filepath)=0
virtual bool write(const void *buf, size_t buf_len)=0
ZstdWriteWrap(WriteWrap &base_wrap)
bool open(const char *filepath) override
bool write(const void *buf, size_t buf_len) override
Span< Value > lookup(const Key &key) const
void add(const Key &key, const Value &value)
void append(const T &value)
void * MEM_mallocN(size_t len, const char *str)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
void MEM_freeN(void *vmemh)
void print_structs_at_address(const SDNA &sdna, int struct_id, const void *data, const void *address, int64_t element_num, std::ostream &stream)
int sdna_struct_id_get_max()
BLO_Write_IDBuffer(ID &id, bool is_undo, bool is_placeholder)
struct ViewLayer * cur_view_layer
float colorspace_scene_linear_to_xyz[3][3]
uint64_t build_commit_timestamp
char colorspace_scene_linear_name[64]
struct bScreen * curscreen
IDTypeBlendWriteFunction blend_write
ID_RuntimeHandle * runtime
unsigned int recalc_up_to_undo_push
LibraryForeachIDCallbackFlag cb_flag
struct PackedFile * packedfile
LibraryRuntimeHandle * runtime
char scene_linear_name[64]
blender::float3x3 scene_linear_to_xyz
MainColorspace colorspace
blender::Map< uint64_t, blender::ImplicitSharingInfoAndData > sharing_info_by_address_id
blender::Map< uint, MemFileChunk * > id_session_uid_mapping
MemFile * written_memfile
uint current_id_session_uid
MemFileChunk * reference_current_chunk
MemFileSharedStorage * shared_storage
char scene_name[MAX_ID_NAME - 2]
ListBase script_directories
struct ListBase asset_shelves_settings
struct ListBase user_keymaps
struct ListBase autoexec_paths
struct ListBase user_keyconfig_prefs
struct ListBase extension_repos
struct ListBase user_menus
struct ListBase asset_libraries
blender::Set< const void * > per_id_addresses_set
struct WriteData::@204076211151137013032026070275231302221043373223 validation_data
std::unique_ptr< blender::dna::pointers::PointersInDNA > sdna_pointers
blender::Map< const void *, uint64_t > pointer_map
struct WriteData::@150011202103324140201313267175203141004052371337 buffer
blender::Set< const void * > per_id_written_shared_addresses
blender::Set< uint64_t > used_ids
struct WriteData::@371046243164336051014002034275316217273200361171 stable_address_ids
uint32_t uncompressed_size
ZstdWriteBlockTask * prev
static void * write_task(void *userdata)
ZstdWriteBlockTask * next
const c_style_mat & ptr() const
Vector< PointerInfo > pointers
struct WorkSpaceInstanceHook * workspace_hook
static DynamicLibrary lib
void BLO_write_double_array(BlendWriter *writer, const int64_t num, const double *data_ptr)
void BLO_write_uint32_array(BlendWriter *writer, const int64_t num, const uint32_t *data_ptr)
static void writedata_do_write(WriteData *wd, const void *mem, const size_t memlen)
static void writestruct_at_address_nr(WriteData *wd, const int filecode, const int struct_nr, const int64_t nr, const void *adr, const void *data)
void blo_write_id_struct(BlendWriter *writer, const int struct_id, const void *id_address, const ID *id)
int BLO_get_struct_id_by_name(const BlendWriter *writer, const char *struct_name)
static void mywrite_id_begin(WriteData *wd, ID *id)
#define ZSTD_COMPRESSION_LEVEL
static uint64_t get_next_stable_address_id(WriteData &wd, uint64_t &hint)
static void prepare_stable_data_block_ids(WriteData &wd, Main &bmain)
static void write_thumb(WriteData *wd, const BlendThumbnail *thumb)
#define writestruct(wd, filecode, struct_id, nr, adr)
static uint64_t get_address_id_int(WriteData &wd, const void *address)
static void current_screen_compat(Main *mainvar, const bool use_active_win, bScreen **r_screen, Scene **r_scene, ViewLayer **r_view_layer)
static uint64_t get_address_id_for_implicit_sharing_data(const void *data)
void BLO_write_pointer_array(BlendWriter *writer, const int64_t num, const void *data_ptr)
void BLO_write_struct_array_by_name(BlendWriter *writer, const char *struct_name, const int64_t array_size, const void *data_ptr)
void BLO_write_struct_at_address_by_id(BlendWriter *writer, const int struct_id, const void *address, const void *data_ptr)
static bool write_file_handle(Main *mainvar, WriteWrap *ww, MemFile *compare, MemFile *current, const int write_flags, const bool use_userdef, const BlendThumbnail *thumb, std::ostream *debug_dst)
static uint64_t get_stable_pointer_hint_for_id(const ID &id, const bool is_undo)
static void writelist_nr(WriteData *wd, const int filecode, const int struct_nr, const ListBase *lb)
static std::string get_blend_file_header()
void BLO_write_int32_array(BlendWriter *writer, const int64_t num, const int32_t *data_ptr)
void BLO_write_struct_by_name(BlendWriter *writer, const char *struct_name, const void *data_ptr)
static void writedata_free(WriteData *wd)
#define DEBUG_BLEND_FILE_SUFFIX
static void write_keymapitem(BlendWriter *writer, const wmKeyMapItem *kmi)
static void write_id(WriteData *wd, ID *id)
static bool do_history(const char *filepath, ReportList *reports)
static void write_renderinfo(WriteData *wd, Main *mainvar)
void BLO_write_struct_list_by_id(BlendWriter *writer, const int struct_id, const ListBase *list)
static void write_userdef(BlendWriter *writer, const UserDef *userdef)
#define writestruct_at_address(wd, filecode, struct_id, nr, adr, data)
static void write_file_main_validate_pre(Main *bmain, ReportList *reports)
void BLO_write_float_array(BlendWriter *writer, const int64_t num, const float *data_ptr)
static void writestruct_nr(WriteData *wd, const int filecode, const int struct_nr, const int64_t nr, const void *adr)
static void write_file_main_validate_post(Main *bmain, ReportList *reports)
void BLO_write_struct_by_id(BlendWriter *writer, const int struct_id, const void *data_ptr)
void BLO_write_struct_array_at_address_by_id(BlendWriter *writer, const int struct_id, const int64_t array_size, const void *address, const void *data_ptr)
void BLO_write_string(BlendWriter *writer, const char *data_ptr)
static WriteData * writedata_new(WriteWrap *ww)
void BLO_write_int8_array(BlendWriter *writer, const int64_t num, const int8_t *data_ptr)
void BLO_write_int16_array(BlendWriter *writer, const int64_t num, const int16_t *data_ptr)
static void writedata(WriteData *wd, const int filecode, const void *data, const size_t len, const void *adr)
void BLO_write_uint8_array(BlendWriter *writer, const int64_t num, const uint8_t *data_ptr)
static void write_libraries(WriteData *wd, Main *bmain)
static void write_global(WriteData *wd, const int fileflags, Main *mainvar)
static bool write_at_address_validate(WriteData *wd, const int filecode, const void *address)
void BLO_write_char_array(BlendWriter *writer, const int64_t num, const char *data_ptr)
static bool mywrite_end(WriteData *wd)
static void mywrite_flush(WriteData *wd)
constexpr uint64_t implicit_sharing_address_id_flag
static blender::Vector< ID * > gather_local_ids_to_write(Main *bmain, const bool is_undo)
void BLO_write_shared_tag(BlendWriter *writer, const void *data)
static void mywrite_id_end(WriteData *wd, ID *)
static void write_blend_file_header(WriteData *wd)
static uint64_t stable_id_from_hint(const uint64_t hint)
bool BLO_write_file(Main *mainvar, const char *filepath, const int write_flags, const BlendFileWriteParams *params, ReportList *reports)
static void write_id_placeholder(WriteData *wd, ID *id)
void BLO_write_struct_array_by_id(BlendWriter *writer, const int struct_id, const int64_t array_size, const void *data_ptr)
bool BLO_write_is_undo(BlendWriter *writer)
static int write_id_direct_linked_data_process_cb(LibraryIDLinkCallbackData *cb_data)
static void mywrite(WriteData *wd, const void *adr, size_t len)
void BLO_write_raw(BlendWriter *writer, const size_t size_in_bytes, const void *data_ptr)
static const void * get_address_id(WriteData &wd, const void *address)
bool BLO_write_file_mem(Main *mainvar, MemFile *compare, MemFile *current, const int write_flags)
static WriteData * mywrite_begin(WriteWrap *ww, MemFile *compare, MemFile *current)
void BLO_write_struct_list_by_name(BlendWriter *writer, const char *struct_name, ListBase *list)
static void write_bhead(WriteData *wd, const BHead &bhead)
static void write_raw_data_in_debug_file(WriteData *wd, const size_t len, const void *address_id, const void *data)
static bool BLO_write_file_impl(Main *mainvar, const char *filepath, const int write_flags, const BlendFileWriteParams *params, ReportList *reports, WriteWrap &ww)
void BLO_write_shared(BlendWriter *writer, const void *data, const size_t approximate_size_in_bytes, const blender::ImplicitSharingInfo *sharing_info, const blender::FunctionRef< void()> write_fn)
void BLO_write_struct_at_address_by_id_with_filecode(BlendWriter *writer, const int filecode, const int struct_id, const void *address, const void *data_ptr)
void BLO_write_float3_array(BlendWriter *writer, const int64_t num, const float *data_ptr)