Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenloader')
-rw-r--r--source/blender/blenloader/BLO_blend_validate.h7
-rw-r--r--source/blender/blenloader/BLO_read_write.h120
-rw-r--r--source/blender/blenloader/BLO_readfile.h198
-rw-r--r--source/blender/blenloader/BLO_undofile.h21
-rw-r--r--source/blender/blenloader/BLO_writefile.h16
-rw-r--r--source/blender/blenloader/CMakeLists.txt2
-rw-r--r--source/blender/blenloader/intern/blend_validate.c5
-rw-r--r--source/blender/blenloader/intern/readblenentry.c96
-rw-r--r--source/blender/blenloader/intern/readfile.c555
-rw-r--r--source/blender/blenloader/intern/readfile.h56
-rw-r--r--source/blender/blenloader/intern/readfile_tempload.c2
-rw-r--r--source/blender/blenloader/intern/undofile.c9
-rw-r--r--source/blender/blenloader/intern/versioning_260.c2
-rw-r--r--source/blender/blenloader/intern/versioning_300.c103
-rw-r--r--source/blender/blenloader/intern/versioning_common.cc43
-rw-r--r--source/blender/blenloader/intern/versioning_common.h36
-rw-r--r--source/blender/blenloader/intern/versioning_defaults.c9
-rw-r--r--source/blender/blenloader/intern/versioning_dna.c10
-rw-r--r--source/blender/blenloader/intern/versioning_legacy.c2
-rw-r--r--source/blender/blenloader/intern/versioning_userdef.c1
-rw-r--r--source/blender/blenloader/intern/writefile.c60
21 files changed, 560 insertions, 793 deletions
diff --git a/source/blender/blenloader/BLO_blend_validate.h b/source/blender/blenloader/BLO_blend_validate.h
index cdbf4bdd952..3a192284661 100644
--- a/source/blender/blenloader/BLO_blend_validate.h
+++ b/source/blender/blenloader/BLO_blend_validate.h
@@ -28,5 +28,12 @@
struct Main;
struct ReportList;
+/**
+ * Check (but do *not* fix) that all linked data-blocks are still valid
+ * (i.e. pointing to the right library).
+ */
bool BLO_main_validate_libraries(struct Main *bmain, struct ReportList *reports);
+/**
+ * * Check (and fix if needed) that shape key's 'from' pointer is valid.
+ */
bool BLO_main_validate_shapekeys(struct Main *bmain, struct ReportList *reports);
diff --git a/source/blender/blenloader/BLO_read_write.h b/source/blender/blenloader/BLO_read_write.h
index ca7ea6d8f09..fe8173e335a 100644
--- a/source/blender/blenloader/BLO_read_write.h
+++ b/source/blender/blenloader/BLO_read_write.h
@@ -58,8 +58,8 @@ struct BlendFileReadReport;
struct Main;
struct ReportList;
-/* Blend Write API
- * ===============
+/* -------------------------------------------------------------------- */
+/** \name Blend Write API
*
* Most functions fall into one of two categories. Either they write a DNA struct or a raw memory
* buffer to the .blend file.
@@ -91,19 +91,25 @@ struct ReportList;
* The code that reads this data might have to correct its byte-order. For the common cases
* there are convenience functions that write and read arrays of simple types such as `int32`.
* Those will correct endianness automatically.
- */
+ * \{ */
-/* Mapping between names and ids. */
+/**
+ * Mapping between names and ids.
+ */
int BLO_get_struct_id_by_name(BlendWriter *writer, const char *struct_name);
#define BLO_get_struct_id(writer, struct_name) SDNA_TYPE_FROM_STRUCT(struct_name)
-/* Write single struct. */
+/**
+ * Write single struct.
+ */
void BLO_write_struct_by_name(BlendWriter *writer, const char *struct_name, const void *data_ptr);
void BLO_write_struct_by_id(BlendWriter *writer, int struct_id, const void *data_ptr);
#define BLO_write_struct(writer, struct_name, data_ptr) \
BLO_write_struct_by_id(writer, BLO_get_struct_id(writer, struct_name), data_ptr)
-/* Write single struct at address. */
+/**
+ * Write single struct at address.
+ */
void BLO_write_struct_at_address_by_id(BlendWriter *writer,
int struct_id,
const void *address,
@@ -112,7 +118,9 @@ void BLO_write_struct_at_address_by_id(BlendWriter *writer,
BLO_write_struct_at_address_by_id( \
writer, BLO_get_struct_id(writer, struct_name), address, data_ptr)
-/* Write single struct at address and specify a filecode. */
+/**
+ * Write single struct at address and specify a file-code.
+ */
void BLO_write_struct_at_address_by_id_with_filecode(
BlendWriter *writer, int filecode, int struct_id, const void *address, const void *data_ptr);
#define BLO_write_struct_at_address_with_filecode( \
@@ -120,7 +128,9 @@ void BLO_write_struct_at_address_by_id_with_filecode(
BLO_write_struct_at_address_by_id_with_filecode( \
writer, filecode, BLO_get_struct_id(writer, struct_name), address, data_ptr)
-/* Write struct array. */
+/**
+ * Write struct array.
+ */
void BLO_write_struct_array_by_name(BlendWriter *writer,
const char *struct_name,
int array_size,
@@ -133,14 +143,18 @@ void BLO_write_struct_array_by_id(BlendWriter *writer,
BLO_write_struct_array_by_id( \
writer, BLO_get_struct_id(writer, struct_name), array_size, data_ptr)
-/* Write struct array at address. */
+/**
+ * Write struct array at address.
+ */
void BLO_write_struct_array_at_address_by_id(
BlendWriter *writer, int struct_id, int array_size, const void *address, const void *data_ptr);
#define BLO_write_struct_array_at_address(writer, struct_name, array_size, address, data_ptr) \
BLO_write_struct_array_at_address_by_id( \
writer, BLO_get_struct_id(writer, struct_name), array_size, address, data_ptr)
-/* Write struct list. */
+/**
+ * Write struct list.
+ */
void BLO_write_struct_list_by_name(BlendWriter *writer,
const char *struct_name,
struct ListBase *list);
@@ -148,7 +162,9 @@ void BLO_write_struct_list_by_id(BlendWriter *writer, int struct_id, struct List
#define BLO_write_struct_list(writer, struct_name, list_ptr) \
BLO_write_struct_list_by_id(writer, BLO_get_struct_id(writer, struct_name), list_ptr)
-/* Write id struct. */
+/**
+ * Write id struct.
+ */
void blo_write_id_struct(BlendWriter *writer,
int struct_id,
const void *id_address,
@@ -156,7 +172,9 @@ void blo_write_id_struct(BlendWriter *writer,
#define BLO_write_id_struct(writer, struct_name, id_address, id) \
blo_write_id_struct(writer, BLO_get_struct_id(writer, struct_name), id_address, id)
-/* Write raw data. */
+/**
+ * Write raw data.
+ */
void BLO_write_raw(BlendWriter *writer, size_t size_in_bytes, const void *data_ptr);
void BLO_write_int32_array(BlendWriter *writer, uint num, const int32_t *data_ptr);
void BLO_write_uint32_array(BlendWriter *writer, uint num, const uint32_t *data_ptr);
@@ -164,13 +182,23 @@ void BLO_write_float_array(BlendWriter *writer, uint num, const float *data_ptr)
void BLO_write_double_array(BlendWriter *writer, uint num, const double *data_ptr);
void BLO_write_float3_array(BlendWriter *writer, uint num, const float *data_ptr);
void BLO_write_pointer_array(BlendWriter *writer, uint num, const void *data_ptr);
+/**
+ * Write a null terminated string.
+ */
void BLO_write_string(BlendWriter *writer, const char *data_ptr);
/* Misc. */
+
+/**
+ * Sometimes different data is written depending on whether the file is saved to disk or used for
+ * undo. This function returns true when the current file-writing is done for undo.
+ */
bool BLO_write_is_undo(BlendWriter *writer);
-/* Blend Read Data API
- * ===================
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Blend Read Data API
*
* Generally, for every BLO_write_* call there should be a corresponding BLO_read_* call.
*
@@ -181,15 +209,18 @@ bool BLO_write_is_undo(BlendWriter *writer);
* updated to be NULL. When it was pointing to NULL before, it will stay that way.
*
* Examples of matching calls:
- * BLO_write_struct(writer, ClothSimSettings, clmd->sim_parms);
- * BLO_read_data_address(reader, &clmd->sim_parms);
*
- * BLO_write_struct_list(writer, TimeMarker, &action->markers);
- * BLO_read_list(reader, &action->markers);
+ * \code{.c}
+ * BLO_write_struct(writer, ClothSimSettings, clmd->sim_parms);
+ * BLO_read_data_address(reader, &clmd->sim_parms);
*
- * BLO_write_int32_array(writer, hmd->totindex, hmd->indexar);
- * BLO_read_int32_array(reader, hmd->totindex, &hmd->indexar);
- */
+ * BLO_write_struct_list(writer, TimeMarker, &action->markers);
+ * BLO_read_list(reader, &action->markers);
+ *
+ * BLO_write_int32_array(writer, hmd->totindex, hmd->indexar);
+ * BLO_read_int32_array(reader, hmd->totindex, &hmd->indexar);
+ * \endcode
+ * \{ */
void *BLO_read_get_new_data_address(BlendDataReader *reader, const void *old_address);
void *BLO_read_get_new_data_address_no_us(BlendDataReader *reader, const void *old_address);
@@ -201,10 +232,16 @@ void *BLO_read_get_new_packed_address(BlendDataReader *reader, const void *old_a
*((void **)ptr_p) = BLO_read_get_new_packed_address((reader), *(ptr_p))
typedef void (*BlendReadListFn)(BlendDataReader *reader, void *data);
+/**
+ * Updates all ->prev and ->next pointers of the list elements.
+ * Updates the list->first and list->last pointers.
+ * When not NULL, calls the callback on every element.
+ */
void BLO_read_list_cb(BlendDataReader *reader, struct ListBase *list, BlendReadListFn callback);
void BLO_read_list(BlendDataReader *reader, struct ListBase *list);
/* Update data pointers and correct byte-order if necessary. */
+
void BLO_read_int32_array(BlendDataReader *reader, int array_size, int32_t **ptr_p);
void BLO_read_uint32_array(BlendDataReader *reader, int array_size, uint32_t **ptr_p);
void BLO_read_float_array(BlendDataReader *reader, int array_size, float **ptr_p);
@@ -213,18 +250,21 @@ void BLO_read_double_array(BlendDataReader *reader, int array_size, double **ptr
void BLO_read_pointer_array(BlendDataReader *reader, void **ptr_p);
/* Misc. */
+
bool BLO_read_requires_endian_switch(BlendDataReader *reader);
bool BLO_read_data_is_undo(BlendDataReader *reader);
void BLO_read_data_globmap_add(BlendDataReader *reader, void *oldaddr, void *newaddr);
void BLO_read_glob_list(BlendDataReader *reader, struct ListBase *list);
struct BlendFileReadReport *BLO_read_data_reports(BlendDataReader *reader);
-/* Blend Read Lib API
- * ===================
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Blend Read Lib API
*
- * This API does almost the same as the Blend Read Data API. However, now only pointers to ID data
- * blocks are updated.
- */
+ * This API does almost the same as the Blend Read Data API.
+ * However, now only pointers to ID data blocks are updated.
+ * \{ */
ID *BLO_read_get_new_id_address(BlendLibReader *reader, struct Library *lib, struct ID *id);
@@ -232,30 +272,44 @@ ID *BLO_read_get_new_id_address(BlendLibReader *reader, struct Library *lib, str
*((void **)id_ptr_p) = (void *)BLO_read_get_new_id_address((reader), (lib), (ID *)*(id_ptr_p))
/* Misc. */
+
bool BLO_read_lib_is_undo(BlendLibReader *reader);
struct Main *BLO_read_lib_get_main(BlendLibReader *reader);
struct BlendFileReadReport *BLO_read_lib_reports(BlendLibReader *reader);
-/* Blend Expand API
- * ===================
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Blend Expand API
*
* BLO_expand has to be called for every data block that should be loaded. If the data block is in
- * a separate .blend file, it will be pulled from there.
- */
+ * a separate `.blend` file, it will be pulled from there.
+ * \{ */
void BLO_expand_id(BlendExpander *expander, struct ID *id);
#define BLO_expand(expander, id) BLO_expand_id(expander, (struct ID *)id)
-/* Report API
- * ===================
- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Report API
+ * \{ */
+/**
+ * This function ensures that reports are printed,
+ * in the case of library linking errors this is important!
+ *
+ * bit kludge but better than doubling up on prints,
+ * we could alternatively have a versions of a report function which forces printing - campbell
+ */
void BLO_reportf_wrap(struct BlendFileReadReport *reports,
eReportType type,
const char *format,
...) ATTR_PRINTF_FORMAT(3, 4);
+/** \} */
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h
index 22182edd070..567886e4d54 100644
--- a/source/blender/blenloader/BLO_readfile.h
+++ b/source/blender/blenloader/BLO_readfile.h
@@ -74,7 +74,7 @@ typedef struct BlendFileData {
int fileflags;
int globalf;
- char filename[1024]; /* 1024 = FILE_MAX */
+ char filepath[1024]; /* 1024 = FILE_MAX */
struct bScreen *curscreen; /* TODO: think this isn't needed anymore? */
struct Scene *curscene;
@@ -144,19 +144,50 @@ typedef enum eBLOReadSkip {
} eBLOReadSkip;
#define BLO_READ_SKIP_ALL (BLO_READ_SKIP_USERDEF | BLO_READ_SKIP_DATA)
+/**
+ * Open a blender file from a pathname. The function returns NULL
+ * and sets a report in the list if it cannot open the file.
+ *
+ * \param filepath: The path of the file to open.
+ * \param reports: If the return value is NULL, errors indicating the cause of the failure.
+ * \return The data of the file.
+ */
BlendFileData *BLO_read_from_file(const char *filepath,
eBLOReadSkip skip_flags,
struct BlendFileReadReport *reports);
+/**
+ * Open a blender file from memory. The function returns NULL
+ * and sets a report in the list if it cannot open the file.
+ *
+ * \param mem: The file data.
+ * \param memsize: The length of \a mem.
+ * \param reports: If the return value is NULL, errors indicating the cause of the failure.
+ * \return The data of the file.
+ */
BlendFileData *BLO_read_from_memory(const void *mem,
int memsize,
eBLOReadSkip skip_flags,
struct ReportList *reports);
+/**
+ * Used for undo/redo, skips part of libraries reading
+ * (assuming their data are already loaded & valid).
+ *
+ * \param oldmain: old main,
+ * from which we will keep libraries and other data-blocks that should not have changed.
+ * \param filename: current file, only for retrieving library data.
+ */
BlendFileData *BLO_read_from_memfile(struct Main *oldmain,
const char *filename,
struct MemFile *memfile,
const struct BlendFileReadParams *params,
struct ReportList *reports);
+/**
+ * Frees a BlendFileData structure and *all* the data associated with it
+ * (the userdef data, and the main libblock data).
+ *
+ * \param bfd: The structure to free.
+ */
void BLO_blendfiledata_free(BlendFileData *bfd);
/** \} */
@@ -170,24 +201,89 @@ typedef struct BLODataBlockInfo {
struct AssetMetaData *asset_data;
} BLODataBlockInfo;
+/**
+ * Open a blendhandle from a file path.
+ *
+ * \param filepath: The file path to open.
+ * \param reports: Report errors in opening the file (can be NULL).
+ * \return A handle on success, or NULL on failure.
+ */
BlendHandle *BLO_blendhandle_from_file(const char *filepath, struct BlendFileReadReport *reports);
+/**
+ * Open a blendhandle from memory.
+ *
+ * \param mem: The data to load from.
+ * \param memsize: The size of the data.
+ * \return A handle on success, or NULL on failure.
+ */
BlendHandle *BLO_blendhandle_from_memory(const void *mem,
int memsize,
struct BlendFileReadReport *reports);
+/**
+ * Gets the names of all the data-blocks in a file of a certain type
+ * (e.g. all the scene names in a file).
+ *
+ * \param bh: The blendhandle to access.
+ * \param ofblocktype: The type of names to get.
+ * \param use_assets_only: Only list IDs marked as assets.
+ * \param r_tot_names: The length of the returned list.
+ * \return A BLI_linklist of strings. The string links should be freed with #MEM_freeN().
+ */
struct LinkNode *BLO_blendhandle_get_datablock_names(BlendHandle *bh,
int ofblocktype,
const bool use_assets_only,
int *r_tot_names);
+/**
+ * Gets the names and asset-data (if ID is an asset) of data-blocks in a file of a certain type.
+ * The data-blocks can be limited to assets.
+ *
+ * \param bh: The blendhandle to access.
+ * \param ofblocktype: The type of names to get.
+ * \param use_assets_only: Limit the result to assets only.
+ * \param r_tot_info_items: The length of the returned list.
+ * \return A BLI_linklist of `BLODataBlockInfo *`.
+ * The links and #BLODataBlockInfo.asset_data should be freed with MEM_freeN.
+ */
struct LinkNode * /*BLODataBlockInfo */ BLO_blendhandle_get_datablock_info(
BlendHandle *bh, int ofblocktype, const bool use_assets_only, int *r_tot_info_items);
+/**
+ * Gets the previews of all the data-blocks in a file of a certain type
+ * (e.g. all the scene previews in a file).
+ *
+ * \param bh: The blendhandle to access.
+ * \param ofblocktype: The type of names to get.
+ * \param r_tot_prev: The length of the returned list.
+ * \return A BLI_linklist of #PreviewImage. The #PreviewImage links should be freed with malloc.
+ */
struct LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *r_tot_prev);
+/**
+ * Get the PreviewImage of a single data block in a file.
+ * (e.g. all the scene previews in a file).
+ *
+ * \param bh: The blendhandle to access.
+ * \param ofblocktype: The type of names to get.
+ * \param name: Name of the block without the ID_ prefix, to read the preview image from.
+ * \return PreviewImage or NULL when no preview Images have been found. Caller owns the returned
+ */
struct PreviewImage *BLO_blendhandle_get_preview_for_id(BlendHandle *bh,
int ofblocktype,
const char *name);
+/**
+ * Gets the names of all the linkable data-block types available in a file.
+ * (e.g. "Scene", "Mesh", "Light", etc.).
+ *
+ * \param bh: The blendhandle to access.
+ * \return A BLI_linklist of strings. The string links should be freed with #MEM_freeN().
+ */
struct LinkNode *BLO_blendhandle_get_linkable_groups(BlendHandle *bh);
+/**
+ * Close and free a blendhandle. The handle becomes invalid after this call.
+ *
+ * \param bh: The handle to close.
+ */
void BLO_blendhandle_close(BlendHandle *bh);
/** \} */
@@ -195,7 +291,25 @@ void BLO_blendhandle_close(BlendHandle *bh);
#define BLO_GROUP_MAX 32
#define BLO_EMBEDDED_STARTUP_BLEND "<startup.blend>"
+/**
+ * Check whether given path ends with a blend file compatible extension
+ * (`.blend`, `.ble` or `.blend.gz`).
+ *
+ * \param str: The path to check.
+ * \return true is this path ends with a blender file extension.
+ */
bool BLO_has_bfile_extension(const char *str);
+/**
+ * Try to explode given path into its 'library components'
+ * (i.e. a .blend file, id type/group, and data-block itself).
+ *
+ * \param path: the full path to explode.
+ * \param r_dir: the string that'll contain path up to blend file itself ('library' path).
+ * WARNING! Must be #FILE_MAX_LIBEXTRA long (it also stores group and name strings)!
+ * \param r_group: the string that'll contain 'group' part of the path, if any. May be NULL.
+ * \param r_name: the string that'll contain data's name part of the path, if any. May be NULL.
+ * \return true if path contains a blend file.
+ */
bool BLO_library_path_explode(const char *path, char *r_dir, char **r_group, char **r_name);
/* -------------------------------------------------------------------- */
@@ -212,14 +326,6 @@ typedef enum eBLOLibLinkFlags {
BLO_LIBLINK_USE_PLACEHOLDERS = 1 << 16,
/** Force loaded ID to be tagged as #LIB_TAG_INDIRECT (used in reload context only). */
BLO_LIBLINK_FORCE_INDIRECT = 1 << 17,
- /**
- * When set, tag ID types that pass the internal check #library_link_idcode_needs_tag_check
- *
- * Currently this is only used to instantiate objects in the scene.
- * Set this from #BLO_library_link_params_init_with_context so callers
- * don't need to remember to set this flag.
- */
- BLO_LIBLINK_NEEDS_ID_TAG_DOIT = 1 << 18,
/** Set fake user on appended IDs. */
BLO_LIBLINK_APPEND_SET_FAKEUSER = 1 << 19,
/** Append (make local) also indirect dependencies of appended IDs coming from other libraries.
@@ -241,7 +347,7 @@ typedef enum eBLOLibLinkFlags {
* #BLO_library_link_begin, #BLO_library_link_named_part & #BLO_library_link_end.
* Wrap these in parameters since it's important both functions receive matching values.
*/
-struct LibraryLink_Params {
+typedef struct LibraryLink_Params {
/** The current main database, e.g. #G_MAIN or `CTX_data_main(C)`. */
struct Main *bmain;
/** Options for linking, used for instantiating. */
@@ -257,7 +363,7 @@ struct LibraryLink_Params {
/** The active 3D viewport (only used to define local-view). */
const struct View3D *v3d;
} context;
-};
+} LibraryLink_Params;
void BLO_library_link_params_init(struct LibraryLink_Params *params,
struct Main *bmain,
@@ -271,20 +377,45 @@ void BLO_library_link_params_init_with_context(struct LibraryLink_Params *params
struct ViewLayer *view_layer,
const struct View3D *v3d);
+/**
+ * Initialize the #BlendHandle for linking library data.
+ *
+ * \param bh: A blender file handle as returned by
+ * #BLO_blendhandle_from_file or #BLO_blendhandle_from_memory.
+ * \param filepath: Used for relative linking, copied to the `lib->filepath`.
+ * \param params: Settings for linking that don't change from beginning to end of linking.
+ * \return the library #Main, to be passed to #BLO_library_link_named_part as \a mainl.
+ */
struct Main *BLO_library_link_begin(BlendHandle **bh,
const char *filepath,
const struct LibraryLink_Params *params);
+/**
+ * Link a named data-block from an external blend file.
+ *
+ * \param mainl: The main database to link from (not the active one).
+ * \param bh: The blender file handle.
+ * \param idcode: The kind of data-block to link.
+ * \param name: The name of the data-block (without the 2 char ID prefix).
+ * \return the linked ID when found.
+ */
struct ID *BLO_library_link_named_part(struct Main *mainl,
BlendHandle **bh,
const short idcode,
const char *name,
const struct LibraryLink_Params *params);
+/**
+ * Finalize linking from a given .blend file (library).
+ * Optionally instance the indirect object/collection in the scene when the flags are set.
+ * \note Do not use \a bh after calling this function, it may frees it.
+ *
+ * \param mainl: The main database to link from (not the active one).
+ * \param bh: The blender file handle (WARNING! may be freed by this function!).
+ * \param params: Settings for linking that don't change from beginning to end of linking.
+ */
void BLO_library_link_end(struct Main *mainl,
BlendHandle **bh,
const struct LibraryLink_Params *params);
-int BLO_library_link_copypaste(struct Main *mainl, BlendHandle *bh, const uint64_t id_types_mask);
-
/**
* Struct for temporarily loading datablocks from a blend file.
*/
@@ -314,6 +445,10 @@ void BLO_library_temp_free(TempLibraryContext *temp_lib_ctx);
void *BLO_library_read_struct(struct FileData *fd, struct BHead *bh, const char *blockname);
/* internal function but we need to expose it */
+/**
+ * Used to link a file (without UI) to the current UI.
+ * Note that it assumes the old pointers in UI are still valid, so old Main is not freed.
+ */
void blo_lib_link_restore(struct Main *oldmain,
struct Main *newmain,
struct wmWindowManager *curwm,
@@ -322,29 +457,50 @@ void blo_lib_link_restore(struct Main *oldmain,
typedef void (*BLOExpandDoitCallback)(void *fdhandle, struct Main *mainvar, void *idv);
+/**
+ * Set the callback func used over all ID data found by \a BLO_expand_main func.
+ *
+ * \param expand_doit_func: Called for each ID block it finds.
+ */
void BLO_main_expander(BLOExpandDoitCallback expand_doit_func);
+/**
+ * Loop over all ID data in Main to mark relations.
+ * Set (id->tag & LIB_TAG_NEED_EXPAND) to mark expanding. Flags get cleared after expanding.
+ *
+ * \param fdhandle: usually filedata, or own handle.
+ * \param mainvar: the Main database to expand.
+ */
void BLO_expand_main(void *fdhandle, struct Main *mainvar);
/**
* Update defaults in startup.blend, without having to save and embed it.
* \note defaults for preferences are stored in `userdef_default.c` and can be updated there.
*/
+/**
+ * Update defaults in startup.blend, without having to save and embed the file.
+ * This function can be emptied each time the startup.blend is updated.
+ *
+ * \note Screen data may be cleared at this point, this will happen in the case
+ * an app-template's data needs to be versioned when read-file is called with "Load UI" disabled.
+ * Versioning the screen data can be safely skipped without "Load UI" since the screen data
+ * will have been versioned when it was first loaded.
+ */
void BLO_update_defaults_startup_blend(struct Main *bmain, const char *app_template);
void BLO_update_defaults_workspace(struct WorkSpace *workspace, const char *app_template);
/* Disable unwanted experimental feature settings on startup. */
void BLO_sanitize_experimental_features_userpref_blend(struct UserDef *userdef);
+/**
+ * Does a very light reading of given .blend file to extract its stored thumbnail.
+ *
+ * \param filepath: The path of the file to extract thumbnail from.
+ * \return The raw thumbnail
+ * (MEM-allocated, as stored in file, use #BKE_main_thumbnail_to_imbuf()
+ * to convert it to ImBuf image).
+ */
struct BlendThumbnail *BLO_thumbnail_from_file(const char *filepath);
-void BLO_object_instantiate_object_base_instance_init(struct Main *bmain,
- struct Collection *collection,
- struct Object *ob,
- struct ViewLayer *view_layer,
- const struct View3D *v3d,
- const int flag,
- bool set_active);
-
/* datafiles (generated theme) */
extern const struct bTheme U_theme_default;
extern const struct UserDef U_default;
diff --git a/source/blender/blenloader/BLO_undofile.h b/source/blender/blenloader/BLO_undofile.h
index 4e240e2462b..0e2c22d7e4d 100644
--- a/source/blender/blenloader/BLO_undofile.h
+++ b/source/blender/blenloader/BLO_undofile.h
@@ -77,7 +77,7 @@ typedef struct {
bool memchunk_identical;
} UndoReader;
-/* actually only used writefile.c */
+/* Actually only used `writefile.c`. */
void BLO_memfile_write_init(MemFileWriteData *mem_data,
MemFile *written_memfile,
@@ -87,14 +87,31 @@ void BLO_memfile_write_finalize(MemFileWriteData *mem_data);
void BLO_memfile_chunk_add(MemFileWriteData *mem_data, const char *buf, size_t size);
/* exports */
+
+/**
+ * Not memfile itself.
+ */
extern void BLO_memfile_free(MemFile *memfile);
+/**
+ * Result is that 'first' is being freed.
+ * to keep list of memfiles consistent, 'first' is always first in list.
+ */
extern void BLO_memfile_merge(MemFile *first, MemFile *second);
+/**
+ * Clear is_identical_future before adding next memfile.
+ */
extern void BLO_memfile_clear_future(MemFile *memfile);
-/* utilities */
+/* Utilities. */
+
extern struct Main *BLO_memfile_main_get(struct MemFile *memfile,
struct Main *bmain,
struct Scene **r_scene);
+/**
+ * Saves .blend using undo buffer.
+ *
+ * \return success.
+ */
extern bool BLO_memfile_write_file(struct MemFile *memfile, const char *filename);
FileReader *BLO_memfile_new_filereader(MemFile *memfile, int undo_direction);
diff --git a/source/blender/blenloader/BLO_writefile.h b/source/blender/blenloader/BLO_writefile.h
index 746c663926d..9bc3714ff38 100644
--- a/source/blender/blenloader/BLO_writefile.h
+++ b/source/blender/blenloader/BLO_writefile.h
@@ -21,9 +21,13 @@
/** \file
* \ingroup blenloader
- * \brief external writefile function prototypes.
+ * \brief external `writefile.c` function prototypes.
*/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct BlendThumbnail;
struct Main;
struct MemFile;
@@ -60,15 +64,25 @@ struct BlendFileWriteParams {
const struct BlendThumbnail *thumb;
};
+/**
+ * \return Success.
+ */
extern bool BLO_write_file(struct Main *mainvar,
const char *filepath,
const int write_flags,
const struct BlendFileWriteParams *params,
struct ReportList *reports);
+/**
+ * \return Success.
+ */
extern bool BLO_write_file_mem(struct Main *mainvar,
struct MemFile *compare,
struct MemFile *current,
int write_flags);
/** \} */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/blenloader/CMakeLists.txt b/source/blender/blenloader/CMakeLists.txt
index b3df5c8aa67..05f74bfa834 100644
--- a/source/blender/blenloader/CMakeLists.txt
+++ b/source/blender/blenloader/CMakeLists.txt
@@ -34,7 +34,6 @@ set(INC
../sequencer
../windowmanager
../../../intern/clog
- ../../../intern/ghost
../../../intern/guardedalloc
# for writefile.c: dna_type_offsets.h
@@ -114,6 +113,7 @@ if(WITH_GTESTS)
tests/blendfile_loading_base_test.h
)
set(TEST_INC
+ ../../../intern/ghost
)
set(TEST_LIB
bf_blenloader
diff --git a/source/blender/blenloader/intern/blend_validate.c b/source/blender/blenloader/intern/blend_validate.c
index 7d641d976e3..333f6e341c6 100644
--- a/source/blender/blenloader/intern/blend_validate.c
+++ b/source/blender/blenloader/intern/blend_validate.c
@@ -47,10 +47,6 @@
#include "readfile.h"
-/**
- * Check (but do *not* fix) that all linked data-blocks are still valid
- * (i.e. pointing to the right library).
- */
bool BLO_main_validate_libraries(Main *bmain, ReportList *reports)
{
ListBase mainlist;
@@ -165,7 +161,6 @@ bool BLO_main_validate_libraries(Main *bmain, ReportList *reports)
return is_valid;
}
-/** Check (and fix if needed) that shape key's 'from' pointer is valid. */
bool BLO_main_validate_shapekeys(Main *bmain, ReportList *reports)
{
ListBase *lb;
diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c
index c0fdfa86907..f3c92aec338 100644
--- a/source/blender/blenloader/intern/readblenentry.c
+++ b/source/blender/blenloader/intern/readblenentry.c
@@ -61,13 +61,6 @@ void BLO_blendhandle_print_sizes(BlendHandle *bh, void *fp);
/* Access routines used by filesel. */
-/**
- * Open a blendhandle from a file path.
- *
- * \param filepath: The file path to open.
- * \param reports: Report errors in opening the file (can be NULL).
- * \return A handle on success, or NULL on failure.
- */
BlendHandle *BLO_blendhandle_from_file(const char *filepath, BlendFileReadReport *reports)
{
BlendHandle *bh;
@@ -77,13 +70,6 @@ BlendHandle *BLO_blendhandle_from_file(const char *filepath, BlendFileReadReport
return bh;
}
-/**
- * Open a blendhandle from memory.
- *
- * \param mem: The data to load from.
- * \param memsize: The size of the data.
- * \return A handle on success, or NULL on failure.
- */
BlendHandle *BLO_blendhandle_from_memory(const void *mem,
int memsize,
BlendFileReadReport *reports)
@@ -130,16 +116,6 @@ void BLO_blendhandle_print_sizes(BlendHandle *bh, void *fp)
fprintf(fp, "]\n");
}
-/**
- * Gets the names of all the data-blocks in a file of a certain type
- * (e.g. all the scene names in a file).
- *
- * \param bh: The blendhandle to access.
- * \param ofblocktype: The type of names to get.
- * \param tot_names: The length of the returned list.
- * \param use_assets_only: Only list IDs marked as assets.
- * \return A BLI_linklist of strings. The string links should be freed with #MEM_freeN().
- */
LinkNode *BLO_blendhandle_get_datablock_names(BlendHandle *bh,
int ofblocktype,
const bool use_assets_only,
@@ -169,17 +145,6 @@ LinkNode *BLO_blendhandle_get_datablock_names(BlendHandle *bh,
return names;
}
-/**
- * Gets the names and asset-data (if ID is an asset) of data-blocks in a file of a certain type.
- * The data-blocks can be limited to assets.
- *
- * \param bh: The blendhandle to access.
- * \param ofblocktype: The type of names to get.
- * \param use_assets_only: Limit the result to assets only.
- * \param tot_info_items: The length of the returned list.
- * \return A BLI_linklist of BLODataBlockInfo *. The links and #BLODataBlockInfo.asset_data should
- * be freed with MEM_freeN.
- */
LinkNode *BLO_blendhandle_get_datablock_info(BlendHandle *bh,
int ofblocktype,
const bool use_assets_only,
@@ -267,15 +232,6 @@ static BHead *blo_blendhandle_read_preview_rects(FileData *fd,
return bhead;
}
-/**
- * Get the PreviewImage of a single data block in a file.
- * (e.g. all the scene previews in a file).
- *
- * \param bh: The blendhandle to access.
- * \param ofblocktype: The type of names to get.
- * \param name: Name of the block without the ID_ prefix, to read the preview image from.
- * \return PreviewImage or NULL when no preview Images have been found. Caller owns the returned
- */
PreviewImage *BLO_blendhandle_get_preview_for_id(BlendHandle *bh,
int ofblocktype,
const char *name)
@@ -315,15 +271,6 @@ PreviewImage *BLO_blendhandle_get_preview_for_id(BlendHandle *bh,
return NULL;
}
-/**
- * Gets the previews of all the data-blocks in a file of a certain type
- * (e.g. all the scene previews in a file).
- *
- * \param bh: The blendhandle to access.
- * \param ofblocktype: The type of names to get.
- * \param r_tot_prev: The length of the returned list.
- * \return A BLI_linklist of PreviewImage. The PreviewImage links should be freed with malloc.
- */
LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *r_tot_prev)
{
FileData *fd = (FileData *)bh;
@@ -384,13 +331,6 @@ LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *r_
return previews;
}
-/**
- * Gets the names of all the linkable data-block types available in a file.
- * (e.g. "Scene", "Mesh", "Light", etc.).
- *
- * \param bh: The blendhandle to access.
- * \return A BLI_linklist of strings. The string links should be freed with #MEM_freeN().
- */
LinkNode *BLO_blendhandle_get_linkable_groups(BlendHandle *bh)
{
FileData *fd = (FileData *)bh;
@@ -418,11 +358,6 @@ LinkNode *BLO_blendhandle_get_linkable_groups(BlendHandle *bh)
return names;
}
-/**
- * Close and free a blendhandle. The handle becomes invalid after this call.
- *
- * \param bh: The handle to close.
- */
void BLO_blendhandle_close(BlendHandle *bh)
{
FileData *fd = (FileData *)bh;
@@ -432,14 +367,6 @@ void BLO_blendhandle_close(BlendHandle *bh)
/**********/
-/**
- * Open a blender file from a pathname. The function returns NULL
- * and sets a report in the list if it cannot open the file.
- *
- * \param filepath: The path of the file to open.
- * \param reports: If the return value is NULL, errors indicating the cause of the failure.
- * \return The data of the file.
- */
BlendFileData *BLO_read_from_file(const char *filepath,
eBLOReadSkip skip_flags,
BlendFileReadReport *reports)
@@ -457,15 +384,6 @@ BlendFileData *BLO_read_from_file(const char *filepath,
return bfd;
}
-/**
- * Open a blender file from memory. The function returns NULL
- * and sets a report in the list if it cannot open the file.
- *
- * \param mem: The file data.
- * \param memsize: The length of \a mem.
- * \param reports: If the return value is NULL, errors indicating the cause of the failure.
- * \return The data of the file.
- */
BlendFileData *BLO_read_from_memory(const void *mem,
int memsize,
eBLOReadSkip skip_flags,
@@ -485,14 +403,6 @@ BlendFileData *BLO_read_from_memory(const void *mem,
return bfd;
}
-/**
- * Used for undo/redo, skips part of libraries reading
- * (assuming their data are already loaded & valid).
- *
- * \param oldmain: old main,
- * from which we will keep libraries and other data-blocks that should not have changed.
- * \param filename: current file, only for retrieving library data.
- */
BlendFileData *BLO_read_from_memfile(Main *oldmain,
const char *filename,
MemFile *memfile,
@@ -548,12 +458,6 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain,
return bfd;
}
-/**
- * Frees a BlendFileData structure and *all* the data associated with it
- * (the userdef data, and the main libblock data).
- *
- * \param bfd: The structure to free.
- */
void BLO_blendfiledata_free(BlendFileData *bfd)
{
if (bfd->main) {
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index e4fe3e8da00..56047bb7f4f 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -195,7 +195,6 @@ static void read_libraries(FileData *basefd, ListBase *mainlist);
static void *read_struct(FileData *fd, BHead *bh, const char *blockname);
static BHead *find_bhead_from_code_name(FileData *fd, const short idcode, const char *name);
static BHead *find_bhead_from_idname(FileData *fd, const char *idname);
-static bool library_link_idcode_needs_tag_check(const short idcode, const int flag);
typedef struct BHeadN {
struct BHeadN *next, *prev;
@@ -215,13 +214,6 @@ typedef struct BHeadN {
* because ID names are used in lookup tables. */
#define BHEAD_USE_READ_ON_DEMAND(bhead) ((bhead)->code == DATA)
-/**
- * This function ensures that reports are printed,
- * in the case of library linking errors this is important!
- *
- * bit kludge but better than doubling up on prints,
- * we could alternatively have a versions of a report function which forces printing - campbell
- */
void BLO_reportf_wrap(BlendFileReadReport *reports, eReportType type, const char *format, ...)
{
char fixed_buf[1024]; /* should be long enough */
@@ -639,7 +631,7 @@ static Main *blo_find_main(FileData *fd, const char *filepath, const char *relab
// printf("blo_find_main: converted to %s\n", name1);
for (m = mainlist->first; m; m = m->next) {
- const char *libname = (m->curlib) ? m->curlib->filepath_abs : m->name;
+ const char *libname = (m->curlib) ? m->curlib->filepath_abs : m->filepath;
if (BLI_path_cmp(name1, libname) == 0) {
if (G.debug & G_DEBUG) {
@@ -998,13 +990,11 @@ static BHead *blo_bhead_read_full(FileData *fd, BHead *thisblock)
}
#endif /* USE_BHEAD_READ_ON_DEMAND */
-/* Warning! Caller's responsibility to ensure given bhead **is** an ID one! */
const char *blo_bhead_id_name(const FileData *fd, const BHead *bhead)
{
return (const char *)POINTER_OFFSET(bhead, sizeof(*bhead) + fd->id_name_offset);
}
-/* 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)
{
BLI_assert(blo_bhead_is_id_valid_type(bhead));
@@ -1149,6 +1139,10 @@ static int *read_file_thumbnail(FileData *fd)
/** \} */
+/* -------------------------------------------------------------------- */
+/** \name File Data API
+ * \{ */
+
static FileData *filedata_new(BlendFileReadReport *reports)
{
BLI_assert(reports != NULL);
@@ -1270,8 +1264,6 @@ static FileData *blo_filedata_from_file_open(const char *filepath, BlendFileRead
return blo_filedata_from_file_descriptor(filepath, reports, file);
}
-/* cannot be called with relative paths anymore! */
-/* on each new library added, it now checks for the current FileData and expands relativeness */
FileData *blo_filedata_from_file(const char *filepath, BlendFileReadReport *reports)
{
FileData *fd = blo_filedata_from_file_open(filepath, reports);
@@ -1412,30 +1404,12 @@ void blo_filedata_free(FileData *fd)
/** \name Public Utilities
* \{ */
-/**
- * Check whether given path ends with a blend file compatible extension
- * (`.blend`, `.ble` or `.blend.gz`).
- *
- * \param str: The path to check.
- * \return true is this path ends with a blender file extension.
- */
bool BLO_has_bfile_extension(const char *str)
{
const char *ext_test[4] = {".blend", ".ble", ".blend.gz", NULL};
return BLI_path_extension_check_array(str, ext_test);
}
-/**
- * Try to explode given path into its 'library components'
- * (i.e. a .blend file, id type/group, and data-block itself).
- *
- * \param path: the full path to explode.
- * \param r_dir: the string that'll contain path up to blend file itself ('library' path).
- * WARNING! Must be #FILE_MAX_LIBEXTRA long (it also stores group and name strings)!
- * \param r_group: the string that'll contain 'group' part of the path, if any. May be NULL.
- * \param r_name: the string that'll contain data's name part of the path, if any. May be NULL.
- * \return true if path contains a blend file.
- */
bool BLO_library_path_explode(const char *path, char *r_dir, char **r_group, char **r_name)
{
/* We might get some data names with slashes,
@@ -1496,14 +1470,6 @@ bool BLO_library_path_explode(const char *path, char *r_dir, char **r_group, cha
return true;
}
-/**
- * Does a very light reading of given .blend file to extract its stored thumbnail.
- *
- * \param filepath: The path of the file to extract thumbnail from.
- * \return The raw thumbnail
- * (MEM-allocated, as stored in file, use #BKE_main_thumbnail_to_imbuf()
- * to convert it to ImBuf image).
- */
BlendThumbnail *BLO_thumbnail_from_file(const char *filepath)
{
FileData *fd;
@@ -1552,7 +1518,6 @@ static void *newdataadr_no_us(FileData *fd, const void *adr)
return oldnewmap_lookup_and_inc(fd->datamap, adr, false);
}
-/* Direct datablocks with global linking. */
void *blo_read_get_new_globaldata_address(FileData *fd, const void *adr)
{
return oldnewmap_lookup_and_inc(fd->globmap, adr, true);
@@ -1574,7 +1539,6 @@ static void *newlibadr(FileData *fd, const void *lib, const void *adr)
return oldnewmap_liblookup(fd->libmap, adr, lib);
}
-/* only lib data */
void *blo_do_versions_newlibadr(FileData *fd, const void *lib, const void *adr)
{
return newlibadr(fd, lib, adr);
@@ -1616,12 +1580,6 @@ static void change_link_placeholder_to_real_ID_pointer(ListBase *mainlist,
}
}
-/* lib linked proxy objects point to our local data, we need
- * to clear that pointer before reading the undo memfile since
- * the object might be removed, it is set again in reading
- * if the local object still exists.
- * This is only valid for local proxy objects though, linked ones should not be affected here.
- */
void blo_clear_proxy_pointers_from_lib(Main *oldmain)
{
LISTBASE_FOREACH (Object *, ob, &oldmain->objects) {
@@ -1681,8 +1639,6 @@ void blo_make_packed_pointer_map(FileData *fd, Main *oldmain)
}
}
-/* set old main packed data to zero if it has been restored */
-/* this works because freeing old main only happens after this call */
void blo_end_packed_pointer_map(FileData *fd, Main *oldmain)
{
OldNew *entry = fd->packedmap->entries;
@@ -1719,7 +1675,6 @@ void blo_end_packed_pointer_map(FileData *fd, Main *oldmain)
}
}
-/* undo file support: add all library pointers in lookup */
void blo_add_library_pointer_map(ListBase *old_mainlist, FileData *fd)
{
ListBase *lbarray[INDEX_ID_MAX];
@@ -1736,8 +1691,6 @@ void blo_add_library_pointer_map(ListBase *old_mainlist, FileData *fd)
fd->old_mainlist = old_mainlist;
}
-/* Build a GSet of old main (we only care about local data here, so we can do that after
- * split_main() call. */
void blo_make_old_idmap_from_main(FileData *fd, Main *bmain)
{
if (fd->old_idmap != NULL) {
@@ -2771,10 +2724,6 @@ static void lib_link_workspace_layout_restore(struct IDNameLib_Map *id_map,
}
}
-/**
- * Used to link a file (without UI) to the current UI.
- * Note that it assumes the old pointers in UI are still valid, so old Main is not freed.
- */
void blo_lib_link_restore(Main *oldmain,
Main *newmain,
wmWindowManager *curwm,
@@ -2903,7 +2852,7 @@ static void lib_link_library(BlendLibReader *UNUSED(reader), Library *UNUSED(lib
* in relation to the blend file. */
static void fix_relpaths_library(const char *basepath, Main *main)
{
- /* BLO_read_from_memory uses a blank filename */
+ /* #BLO_read_from_memory uses a blank file-path. */
if (basepath == NULL || basepath[0] == '\0') {
LISTBASE_FOREACH (Library *, lib, &main->libraries) {
/* when loading a linked lib into a file which has not been saved,
@@ -3557,25 +3506,25 @@ static BHead *read_global(BlendFileData *bfd, FileData *fd, BHead *bhead)
bfd->fileflags = fg->fileflags;
bfd->globalf = fg->globalf;
- BLI_strncpy(bfd->filename, fg->filename, sizeof(bfd->filename));
+ STRNCPY(bfd->filepath, fg->filepath);
- /* Error in 2.65 and older: main->name was not set if you save from startup
+ /* Error in 2.65 and older: `main->filepath` was not set if you save from startup
* (not after loading file). */
- if (bfd->filename[0] == 0) {
+ if (bfd->filepath[0] == 0) {
if (fd->fileversion < 265 || (fd->fileversion == 265 && fg->subversion < 1)) {
if ((G.fileflags & G_FILE_RECOVER_READ) == 0) {
- BLI_strncpy(bfd->filename, BKE_main_blendfile_path(bfd->main), sizeof(bfd->filename));
+ STRNCPY(bfd->filepath, BKE_main_blendfile_path(bfd->main));
}
}
- /* early 2.50 version patch - filename not in FileGlobal struct at all */
+ /* early 2.50 version patch - filepath not in FileGlobal struct at all */
if (fd->fileversion <= 250) {
- BLI_strncpy(bfd->filename, BKE_main_blendfile_path(bfd->main), sizeof(bfd->filename));
+ STRNCPY(bfd->filepath, BKE_main_blendfile_path(bfd->main));
}
}
if (G.fileflags & G_FILE_RECOVER_READ) {
- BLI_strncpy(fd->relabase, fg->filename, sizeof(fd->relabase));
+ BLI_strncpy(fd->relabase, fg->filepath, sizeof(fd->relabase));
}
bfd->curscreen = fg->curscreen;
@@ -3671,7 +3620,7 @@ static void do_versions_after_linking(Main *main, ReportList *reports)
CLOG_INFO(&LOG,
2,
"Processing %s (%s), %d.%d",
- main->curlib ? main->curlib->filepath : main->name,
+ main->curlib ? main->curlib->filepath : main->filepath,
main->curlib ? "LIB" : "MAIN",
main->versionfile,
main->subversionfile);
@@ -3909,7 +3858,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
if ((fd->skip_flags & BLO_READ_SKIP_DATA) == 0) {
BLI_addtail(&mainlist, bfd->main);
fd->mainlist = &mainlist;
- BLI_strncpy(bfd->main->name, filepath, sizeof(bfd->main->name));
+ STRNCPY(bfd->main->filepath, filepath);
}
if (G.background) {
@@ -4384,23 +4333,11 @@ static void expand_id(BlendExpander *expander, ID *id)
expand_id_embedded_id(expander, id);
}
-/**
- * Set the callback func used over all ID data found by \a BLO_expand_main func.
- *
- * \param expand_doit_func: Called for each ID block it finds.
- */
void BLO_main_expander(BLOExpandDoitCallback expand_doit_func)
{
expand_doit = expand_doit_func;
}
-/**
- * Loop over all ID data in Main to mark relations.
- * Set (id->tag & LIB_TAG_NEED_EXPAND) to mark expanding. Flags get cleared after expanding.
- *
- * \param fdhandle: usually filedata, or own handle.
- * \param mainvar: the Main database to expand.
- */
void BLO_expand_main(void *fdhandle, Main *mainvar)
{
ListBase *lbarray[INDEX_ID_MAX];
@@ -4441,290 +4378,6 @@ void BLO_expand_main(void *fdhandle, Main *mainvar)
/** \name Library Linking (helper functions)
* \{ */
-static bool object_in_any_scene(Main *bmain, Object *ob)
-{
- LISTBASE_FOREACH (Scene *, sce, &bmain->scenes) {
- if (BKE_scene_object_find(sce, ob)) {
- return true;
- }
- }
-
- return false;
-}
-
-static bool object_in_any_collection(Main *bmain, Object *ob)
-{
- LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
- if (BKE_collection_has_object(collection, ob)) {
- return true;
- }
- }
-
- LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
- if (scene->master_collection != NULL &&
- BKE_collection_has_object(scene->master_collection, ob)) {
- return true;
- }
- }
-
- return false;
-}
-
-/**
- * Shared operations to perform on the object's base after adding it to the scene.
- */
-static void object_base_instance_init(
- Object *ob, ViewLayer *view_layer, const View3D *v3d, const int flag, bool set_active)
-{
- Base *base = BKE_view_layer_base_find(view_layer, ob);
-
- if (v3d != NULL) {
- base->local_view_bits |= v3d->local_view_uuid;
- }
-
- if (flag & FILE_AUTOSELECT) {
- /* All objects that use #FILE_AUTOSELECT must be selectable (unless linking data). */
- BLI_assert((base->flag & BASE_SELECTABLE) || (flag & FILE_LINK));
- if (base->flag & BASE_SELECTABLE) {
- base->flag |= BASE_SELECTED;
- }
- }
-
- if (set_active) {
- view_layer->basact = base;
- }
-
- BKE_scene_object_base_flag_sync_from_base(base);
-}
-
-/**
- * Exported for link/append to create objects as well.
- */
-void BLO_object_instantiate_object_base_instance_init(Main *bmain,
- Collection *collection,
- Object *ob,
- ViewLayer *view_layer,
- const View3D *v3d,
- const int flag,
- bool set_active)
-{
- /* Auto-select and appending. */
- if ((flag & FILE_AUTOSELECT) && ((flag & FILE_LINK) == 0)) {
- /* While in general the object should not be manipulated,
- * when the user requests the object to be selected, ensure it's visible and selectable. */
- ob->visibility_flag &= ~(OB_HIDE_VIEWPORT | OB_HIDE_SELECT);
- }
-
- BKE_collection_object_add(bmain, collection, ob);
-
- object_base_instance_init(ob, view_layer, v3d, flag, set_active);
-}
-
-static void add_loose_objects_to_scene(Main *mainvar,
- Main *bmain,
- Scene *scene,
- ViewLayer *view_layer,
- const View3D *v3d,
- Library *lib,
- const int flag)
-{
- Collection *active_collection = NULL;
- const bool do_append = (flag & FILE_LINK) == 0;
-
- BLI_assert(scene);
-
- /* Give all objects which are LIB_TAG_INDIRECT a base,
- * or for a collection when *lib has been set. */
- LISTBASE_FOREACH (Object *, ob, &mainvar->objects) {
- /* NOTE: Even if this is a directly linked object and is tagged for instantiation, it might
- * have already been instantiated through one of its owner collections, in which case we do not
- * want to re-instantiate it in the active collection here. */
- bool do_it = (ob->id.tag & LIB_TAG_DOIT) != 0 && !BKE_scene_object_find(scene, ob);
- if (do_it ||
- ((ob->id.tag & LIB_TAG_INDIRECT) != 0 && (ob->id.tag & LIB_TAG_PRE_EXISTING) == 0)) {
- if (do_append) {
- if (ob->id.us == 0) {
- do_it = true;
- }
- else if ((ob->id.lib == lib) && !object_in_any_collection(bmain, ob)) {
- /* When appending, make sure any indirectly loaded object gets a base,
- * when they are not part of any collection yet. */
- do_it = true;
- }
- }
-
- if (do_it) {
- /* Find or add collection as needed. */
- if (active_collection == NULL) {
- if (flag & FILE_ACTIVE_COLLECTION) {
- LayerCollection *lc = BKE_layer_collection_get_active(view_layer);
- active_collection = lc->collection;
- }
- else {
- active_collection = BKE_collection_add(bmain, scene->master_collection, NULL);
- }
- }
-
- CLAMP_MIN(ob->id.us, 0);
- ob->mode = OB_MODE_OBJECT;
-
- /* Do NOT make base active here! screws up GUI stuff,
- * if you want it do it at the editor level. */
- const bool set_active = false;
- BLO_object_instantiate_object_base_instance_init(
- bmain, active_collection, ob, view_layer, v3d, flag, set_active);
-
- ob->id.tag &= ~LIB_TAG_INDIRECT;
- ob->id.flag &= ~LIB_INDIRECT_WEAK_LINK;
- ob->id.tag |= LIB_TAG_EXTERN;
- }
- }
- }
-}
-
-static void add_loose_object_data_to_scene(Main *mainvar,
- Main *bmain,
- Scene *scene,
- ViewLayer *view_layer,
- const View3D *v3d,
- const int flag)
-{
- if ((flag & BLO_LIBLINK_OBDATA_INSTANCE) == 0) {
- return;
- }
-
- Collection *active_collection = scene->master_collection;
- if (flag & FILE_ACTIVE_COLLECTION) {
- LayerCollection *lc = BKE_layer_collection_get_active(view_layer);
- active_collection = lc->collection;
- }
-
- /* Do not re-instantiate obdata IDs that are already instantiated by an object. */
- LISTBASE_FOREACH (Object *, ob, &mainvar->objects) {
- if ((ob->id.tag & LIB_TAG_PRE_EXISTING) == 0 && ob->data != NULL) {
- ID *obdata = ob->data;
- BLI_assert(ID_REAL_USERS(obdata) > 0);
- if ((obdata->tag & LIB_TAG_PRE_EXISTING) == 0) {
- obdata->tag &= ~LIB_TAG_DOIT;
- }
- }
- }
-
- /* Loop over all ID types, instancing object-data for ID types that have support for it. */
- ListBase *lbarray[INDEX_ID_MAX];
- int i = set_listbasepointers(mainvar, lbarray);
- while (i--) {
- const short idcode = BKE_idtype_idcode_from_index(i);
- if (!OB_DATA_SUPPORT_ID(idcode)) {
- continue;
- }
-
- LISTBASE_FOREACH (ID *, id, lbarray[i]) {
- if (id->tag & LIB_TAG_DOIT) {
- const int type = BKE_object_obdata_to_type(id);
- BLI_assert(type != -1);
- Object *ob = BKE_object_add_only_object(bmain, type, id->name + 2);
- ob->data = id;
- id_us_plus(id);
- BKE_object_materials_test(bmain, ob, ob->data);
-
- /* Do NOT make base active here! screws up GUI stuff,
- * if you want it do it at the editor level. */
- bool set_active = false;
- BLO_object_instantiate_object_base_instance_init(
- bmain, active_collection, ob, view_layer, v3d, flag, set_active);
-
- copy_v3_v3(ob->loc, scene->cursor.location);
- }
- }
- }
-}
-
-static void add_collections_to_scene(Main *mainvar,
- Main *bmain,
- Scene *scene,
- ViewLayer *view_layer,
- const View3D *v3d,
- Library *lib,
- const int flag)
-{
- Collection *active_collection = scene->master_collection;
- if (flag & FILE_ACTIVE_COLLECTION) {
- LayerCollection *lc = BKE_layer_collection_get_active(view_layer);
- active_collection = lc->collection;
- }
-
- /* Give all objects which are tagged a base. */
- LISTBASE_FOREACH (Collection *, collection, &mainvar->collections) {
- if ((flag & BLO_LIBLINK_COLLECTION_INSTANCE) && (collection->id.tag & LIB_TAG_DOIT)) {
- /* Any indirect collection should not have been tagged. */
- BLI_assert((collection->id.tag & LIB_TAG_INDIRECT) == 0);
-
- /* BKE_object_add(...) messes with the selection. */
- Object *ob = BKE_object_add_only_object(bmain, OB_EMPTY, collection->id.name + 2);
- ob->type = OB_EMPTY;
- ob->empty_drawsize = U.collection_instance_empty_size;
-
- const bool set_selected = (flag & FILE_AUTOSELECT) != 0;
- /* TODO: why is it OK to make this active here but not in other situations?
- * See other callers of #object_base_instance_init */
- const bool set_active = set_selected;
- BLO_object_instantiate_object_base_instance_init(
- bmain, active_collection, ob, view_layer, v3d, flag, set_active);
-
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
-
- /* Assign the collection. */
- ob->instance_collection = collection;
- id_us_plus(&collection->id);
- ob->transflag |= OB_DUPLICOLLECTION;
- copy_v3_v3(ob->loc, scene->cursor.location);
- }
- /* We do not want to force instantiation of indirectly linked collections,
- * not even when appending. Users can now easily instantiate collections (and their objects)
- * as needed by themselves. See T67032. */
- else if ((collection->id.tag & LIB_TAG_INDIRECT) == 0) {
- bool do_add_collection = (collection->id.tag & LIB_TAG_DOIT) != 0;
- if (!do_add_collection) {
- /* We need to check that objects in that collections are already instantiated in a scene.
- * Otherwise, it's better to add the collection to the scene's active collection, than to
- * instantiate its objects in active scene's collection directly. See T61141.
- * Note that we only check object directly into that collection,
- * not recursively into its children.
- */
- LISTBASE_FOREACH (CollectionObject *, coll_ob, &collection->gobject) {
- Object *ob = coll_ob->ob;
- if ((ob->id.tag & (LIB_TAG_PRE_EXISTING | LIB_TAG_DOIT | LIB_TAG_INDIRECT)) == 0 &&
- (ob->id.lib == lib) && (object_in_any_scene(bmain, ob) == false)) {
- do_add_collection = true;
- break;
- }
- }
- }
- if (do_add_collection) {
- /* Add collection as child of active collection. */
- BKE_collection_child_add(bmain, active_collection, collection);
-
- if (flag & FILE_AUTOSELECT) {
- LISTBASE_FOREACH (CollectionObject *, coll_ob, &collection->gobject) {
- Object *ob = coll_ob->ob;
- Base *base = BKE_view_layer_base_find(view_layer, ob);
- if (base) {
- base->flag |= BASE_SELECTED;
- BKE_scene_object_base_flag_sync_from_base(base);
- }
- }
- }
-
- /* Those are kept for safety and consistency, but should not be needed anymore? */
- collection->id.tag &= ~LIB_TAG_INDIRECT;
- collection->id.flag &= ~LIB_INDIRECT_WEAK_LINK;
- collection->id.tag |= LIB_TAG_EXTERN;
- }
- }
- }
-}
-
/* returns true if the item was found
* but it may already have already been appended/linked */
static ID *link_named_part(
@@ -4774,75 +4427,9 @@ static ID *link_named_part(
/* if we found the id but the id is NULL, this is really bad */
BLI_assert(!((bhead != NULL) && (id == NULL)));
- /* Tag as loose object (or data associated with objects)
- * needing to be instantiated in #LibraryLink_Params.scene. */
- if ((id != NULL) && (flag & BLO_LIBLINK_NEEDS_ID_TAG_DOIT)) {
- if (library_link_idcode_needs_tag_check(idcode, flag)) {
- id->tag |= LIB_TAG_DOIT;
- }
- }
-
return id;
}
-/**
- * Simple reader for copy/paste buffers.
- */
-int BLO_library_link_copypaste(Main *mainl, BlendHandle *bh, const uint64_t id_types_mask)
-{
- FileData *fd = (FileData *)(bh);
- BHead *bhead;
- int num_directly_linked = 0;
-
- for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
- ID *id = NULL;
-
- if (bhead->code == ENDB) {
- break;
- }
-
- if (blo_bhead_is_id_valid_type(bhead) && BKE_idtype_idcode_is_linkable((short)bhead->code) &&
- (id_types_mask == 0 ||
- (BKE_idtype_idcode_to_idfilter((short)bhead->code) & id_types_mask) != 0)) {
- read_libblock(fd, mainl, bhead, LIB_TAG_NEED_EXPAND | LIB_TAG_EXTERN, false, &id);
- num_directly_linked++;
- }
-
- if (id) {
- /* sort by name in list */
- ListBase *lb = which_libbase(mainl, GS(id->name));
- id_sort_by_name(lb, id, NULL);
-
- /* Tag as loose object (or data associated with objects)
- * needing to be instantiated (see also #link_named_part and its usage of
- * #BLO_LIBLINK_NEEDS_ID_TAG_DOIT above). */
- if (library_link_idcode_needs_tag_check(GS(id->name), BLO_LIBLINK_NEEDS_ID_TAG_DOIT)) {
- id->tag |= LIB_TAG_DOIT;
- }
-
- if (bhead->code == ID_OB) {
- /* Instead of instancing Base's directly, postpone until after collections are loaded
- * otherwise the base's flag is set incorrectly when collections are used */
- Object *ob = (Object *)id;
- ob->mode = OB_MODE_OBJECT;
- /* ensure add_loose_objects_to_scene runs on this object */
- BLI_assert(id->us == 0);
- }
- }
- }
-
- return num_directly_linked;
-}
-
-/**
- * Link a named data-block from an external blend file.
- *
- * \param mainl: The main database to link from (not the active one).
- * \param bh: The blender file handle.
- * \param idcode: The kind of data-block to link.
- * \param name: The name of the data-block (without the 2 char ID prefix).
- * \return the linked ID when found.
- */
ID *BLO_library_link_named_part(Main *mainl,
BlendHandle **bh,
const short idcode,
@@ -4855,41 +4442,10 @@ ID *BLO_library_link_named_part(Main *mainl,
/* common routine to append/link something from a library */
-/**
- * Checks if the \a idcode needs to be tagged with #LIB_TAG_DOIT when linking/appending.
- */
-static bool library_link_idcode_needs_tag_check(const short idcode, const int flag)
-{
- if (flag & BLO_LIBLINK_NEEDS_ID_TAG_DOIT) {
- /* Always true because of #add_loose_objects_to_scene & #add_collections_to_scene. */
- if (ELEM(idcode, ID_OB, ID_GR)) {
- return true;
- }
- if (flag & BLO_LIBLINK_OBDATA_INSTANCE) {
- if (OB_DATA_SUPPORT_ID(idcode)) {
- return true;
- }
- }
- }
- return false;
-}
-
-/**
- * Clears #LIB_TAG_DOIT based on the result of #library_link_idcode_needs_tag_check.
- */
-static void library_link_clear_tag(Main *mainvar, const int flag)
-{
- for (int i = 0; i < INDEX_ID_MAX; i++) {
- const short idcode = BKE_idtype_idcode_from_index(i);
- BLI_assert(idcode != -1);
- if (library_link_idcode_needs_tag_check(idcode, flag)) {
- BKE_main_id_tag_idcode(mainvar, idcode, LIB_TAG_DOIT, false);
- }
- }
-}
-
-static Main *library_link_begin(
- Main *mainvar, FileData **fd, const char *filepath, const int flag, const int id_tag_extra)
+static Main *library_link_begin(Main *mainvar,
+ FileData **fd,
+ const char *filepath,
+ const int id_tag_extra)
{
Main *mainl;
@@ -4902,11 +4458,6 @@ static Main *library_link_begin(
(*fd)->mainlist = MEM_callocN(sizeof(ListBase), "FileData.mainlist");
- if (flag & BLO_LIBLINK_NEEDS_ID_TAG_DOIT) {
- /* Clear for objects and collections instantiating tag. */
- library_link_clear_tag(mainvar, flag);
- }
-
/* make mains */
blo_split_main((*fd)->mainlist, mainvar);
@@ -4945,30 +4496,18 @@ void BLO_library_link_params_init_with_context(struct LibraryLink_Params *params
{
BLO_library_link_params_init(params, bmain, flag, id_tag_extra);
if (scene != NULL) {
- /* Tagging is needed for instancing. */
- params->flag |= BLO_LIBLINK_NEEDS_ID_TAG_DOIT;
-
params->context.scene = scene;
params->context.view_layer = view_layer;
params->context.v3d = v3d;
}
}
-/**
- * Initialize the #BlendHandle for linking library data.
- *
- * \param bh: A blender file handle as returned by
- * #BLO_blendhandle_from_file or #BLO_blendhandle_from_memory.
- * \param filepath: Used for relative linking, copied to the `lib->filepath`.
- * \param params: Settings for linking that don't change from beginning to end of linking.
- * \return the library #Main, to be passed to #BLO_library_link_named_part as \a mainl.
- */
Main *BLO_library_link_begin(BlendHandle **bh,
const char *filepath,
const struct LibraryLink_Params *params)
{
FileData *fd = (FileData *)(*bh);
- return library_link_begin(params->bmain, &fd, filepath, params->flag, params->id_tag_extra);
+ return library_link_begin(params->bmain, &fd, filepath, params->id_tag_extra);
}
static void split_main_newid(Main *mainptr, Main *main_newid)
@@ -4976,7 +4515,7 @@ static void split_main_newid(Main *mainptr, Main *main_newid)
/* We only copy the necessary subset of data in this temp main. */
main_newid->versionfile = mainptr->versionfile;
main_newid->subversionfile = mainptr->subversionfile;
- BLI_strncpy(main_newid->name, mainptr->name, sizeof(main_newid->name));
+ STRNCPY(main_newid->filepath, mainptr->filepath);
main_newid->curlib = mainptr->curlib;
ListBase *lbarray[INDEX_ID_MAX];
@@ -4995,19 +4534,7 @@ static void split_main_newid(Main *mainptr, Main *main_newid)
}
}
-/**
- * \param scene: The scene in which to instantiate objects/collections
- * (if NULL, no instantiation is done).
- * \param v3d: The active 3D viewport.
- * (only to define active layers for instantiated objects & collections, can be NULL).
- */
-static void library_link_end(Main *mainl,
- FileData **fd,
- Main *bmain,
- const int flag,
- Scene *scene,
- ViewLayer *view_layer,
- const View3D *v3d)
+static void library_link_end(Main *mainl, FileData **fd, const int flag)
{
Main *mainvar;
Library *curlib;
@@ -5092,22 +4619,6 @@ static void library_link_end(Main *mainl,
/* Make all relative paths, relative to the open blend file. */
fix_relpaths_library(BKE_main_blendfile_path(mainvar), mainvar);
- /* Give a base to loose objects and collections.
- * Only directly linked objects & collections are instantiated by
- * #BLO_library_link_named_part & co,
- * here we handle indirect ones and other possible edge-cases. */
- if (flag & BLO_LIBLINK_NEEDS_ID_TAG_DOIT) {
- /* Should always be true. */
- if (scene != NULL) {
- add_collections_to_scene(mainvar, bmain, scene, view_layer, v3d, curlib, flag);
- add_loose_objects_to_scene(mainvar, bmain, scene, view_layer, v3d, curlib, flag);
- add_loose_object_data_to_scene(mainvar, bmain, scene, view_layer, v3d, flag);
- }
-
- /* Clear objects and collections instantiating tag. */
- library_link_clear_tag(mainvar, flag);
- }
-
/* patch to prevent switch_endian happens twice */
if ((*fd)->flags & FD_FLAGS_SWITCH_ENDIAN) {
blo_filedata_free(*fd);
@@ -5115,25 +4626,10 @@ static void library_link_end(Main *mainl,
}
}
-/**
- * Finalize linking from a given .blend file (library).
- * Optionally instance the indirect object/collection in the scene when the flags are set.
- * \note Do not use \a bh after calling this function, it may frees it.
- *
- * \param mainl: The main database to link from (not the active one).
- * \param bh: The blender file handle (WARNING! may be freed by this function!).
- * \param params: Settings for linking that don't change from beginning to end of linking.
- */
void BLO_library_link_end(Main *mainl, BlendHandle **bh, const struct LibraryLink_Params *params)
{
FileData *fd = (FileData *)(*bh);
- library_link_end(mainl,
- &fd,
- params->bmain,
- params->flag,
- params->context.scene,
- params->context.view_layer,
- params->context.v3d);
+ library_link_end(mainl, &fd, params->flag);
*bh = (BlendHandle *)fd;
}
@@ -5485,11 +4981,6 @@ bool BLO_read_requires_endian_switch(BlendDataReader *reader)
return (reader->fd->flags & FD_FLAGS_SWITCH_ENDIAN) != 0;
}
-/**
- * Updates all ->prev and ->next pointers of the list elements.
- * Updates the list->first and list->last pointers.
- * When not NULL, calls the callback on every element.
- */
void BLO_read_list_cb(BlendDataReader *reader, ListBase *list, BlendReadListFn callback)
{
if (BLI_listbase_is_empty(list)) {
diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h
index 75152a05063..3b5be3dd013 100644
--- a/source/blender/blenloader/intern/readfile.h
+++ b/source/blender/blenloader/intern/readfile.h
@@ -131,6 +131,11 @@ void blo_split_main(ListBase *mainlist, struct Main *main);
BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath);
+/**
+ * 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, struct BlendFileReadReport *reports);
FileData *blo_filedata_from_memory(const void *mem,
int memsize,
@@ -139,10 +144,28 @@ FileData *blo_filedata_from_memfile(struct MemFile *memfile,
const struct BlendFileReadParams *params,
struct BlendFileReadReport *reports);
+/**
+ * Lib linked proxy objects point to our local data, we need
+ * to clear that pointer before reading the undo memfile since
+ * the object might be removed, it is set again in reading
+ * if the local object still exists.
+ * This is only valid for local proxy objects though, linked ones should not be affected here.
+ */
void blo_clear_proxy_pointers_from_lib(struct Main *oldmain);
void blo_make_packed_pointer_map(FileData *fd, struct Main *oldmain);
+/**
+ * Set old main packed data to zero if it has been restored
+ * this works because freeing old main only happens after this call.
+ */
void blo_end_packed_pointer_map(FileData *fd, struct Main *oldmain);
+/**
+ * Undo file support: add all library pointers in lookup.
+ */
void blo_add_library_pointer_map(ListBase *old_mainlist, FileData *fd);
+/**
+ * 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, struct Main *bmain);
BHead *blo_read_asset_data_block(FileData *fd, BHead *bhead, struct AssetMetaData **r_asset_data);
@@ -157,23 +180,48 @@ BHead *blo_bhead_first(FileData *fd);
BHead *blo_bhead_next(FileData *fd, BHead *thisblock);
BHead *blo_bhead_prev(FileData *fd, BHead *thisblock);
+/**
+ * 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!
+ */
struct 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(struct SDNA *sdna, const int versionfile, const int subversionfile);
void blo_do_versions_oldnewmap_insert(struct OldNewMap *onm,
const void *oldaddr,
void *newaddr,
int nr);
+/**
+ * Only library data.
+ */
void *blo_do_versions_newlibadr(struct FileData *fd, const void *lib, const void *adr);
void *blo_do_versions_newlibadr_us(struct FileData *fd, const void *lib, 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(struct Object *ob);
void blo_do_versions_key_uidgen(struct Key *key);
+/**
+ * Patching #UserDef struct and Themes.
+ */
void blo_do_versions_userdef(struct UserDef *userdef);
void blo_do_versions_pre250(struct FileData *fd, struct Library *lib, struct Main *bmain);
@@ -193,6 +241,10 @@ void do_versions_after_linking_290(struct Main *bmain, struct ReportList *report
void do_versions_after_linking_300(struct Main *bmain, struct ReportList *reports);
void do_versions_after_linking_cycles(struct Main *bmain);
-/* This is rather unfortunate to have to expose this here, but better use that nasty hack in
- * do_version than readfile itself. */
+/**
+ * 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(struct FileData *fd, const void *adr);
diff --git a/source/blender/blenloader/intern/readfile_tempload.c b/source/blender/blenloader/intern/readfile_tempload.c
index 1b1cbb29ef5..311732adf99 100644
--- a/source/blender/blenloader/intern/readfile_tempload.c
+++ b/source/blender/blenloader/intern/readfile_tempload.c
@@ -39,7 +39,7 @@ TempLibraryContext *BLO_library_temp_load_id(struct Main *real_main,
temp_lib_ctx->bf_reports.reports = reports;
/* Copy the file path so any path remapping is performed properly. */
- STRNCPY(temp_lib_ctx->bmain_base->name, real_main->name);
+ STRNCPY(temp_lib_ctx->bmain_base->filepath, real_main->filepath);
temp_lib_ctx->blendhandle = BLO_blendhandle_from_file(blend_file_path,
&temp_lib_ctx->bf_reports);
diff --git a/source/blender/blenloader/intern/undofile.c b/source/blender/blenloader/intern/undofile.c
index 62072cf7df5..dfa6135dac9 100644
--- a/source/blender/blenloader/intern/undofile.c
+++ b/source/blender/blenloader/intern/undofile.c
@@ -55,7 +55,6 @@
/* **************** support for memory-write, for undo buffers *************** */
-/* not memfile itself */
void BLO_memfile_free(MemFile *memfile)
{
MemFileChunk *chunk;
@@ -69,8 +68,6 @@ void BLO_memfile_free(MemFile *memfile)
memfile->size = 0;
}
-/* to keep list of memfiles consistent, 'first' is always first in list */
-/* result is that 'first' is being freed */
void BLO_memfile_merge(MemFile *first, MemFile *second)
{
/* We use this mapping to store the memory buffers from second memfile chunks which are not owned
@@ -106,7 +103,6 @@ void BLO_memfile_merge(MemFile *first, MemFile *second)
BLO_memfile_free(first);
}
-/* Clear is_identical_future before adding next memfile. */
void BLO_memfile_clear_future(MemFile *memfile)
{
LISTBASE_FOREACH (MemFileChunk *, chunk, &memfile->chunks) {
@@ -216,11 +212,6 @@ struct Main *BLO_memfile_main_get(struct MemFile *memfile,
return bmain_undo;
}
-/**
- * Saves .blend using undo buffer.
- *
- * \return success.
- */
bool BLO_memfile_write_file(struct MemFile *memfile, const char *filename)
{
MemFileChunk *chunk;
diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c
index c4d04392cba..8a22fd07c24 100644
--- a/source/blender/blenloader/intern/versioning_260.c
+++ b/source/blender/blenloader/intern/versioning_260.c
@@ -1892,7 +1892,7 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *bmain)
for (cu = bmain->curves.first; cu; cu = cu->id.next) {
if (cu->flag & (CU_FRONT | CU_BACK)) {
- if (cu->ext1 != 0.0f || cu->ext2 != 0.0f) {
+ if (cu->extrude != 0.0f || cu->bevel_radius != 0.0f) {
Nurb *nu;
for (nu = cu->nurb.first; nu; nu = nu->next) {
diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c
index 125f3be0dd1..7a7f12a7e58 100644
--- a/source/blender/blenloader/intern/versioning_300.c
+++ b/source/blender/blenloader/intern/versioning_300.c
@@ -1321,13 +1321,16 @@ static void version_liboverride_rnacollections_insertion_object_constraints(
opop->subitem_local_name,
offsetof(bConstraint, name),
opop->subitem_local_index);
- if (constraint_anchor == NULL || constraint_anchor->next == NULL) {
+ bConstraint *constraint_src = constraint_anchor != NULL ? constraint_anchor->next :
+ constraints->first;
+
+ if (constraint_src == NULL) {
/* Invalid case, just remove that override property operation. */
- CLOG_ERROR(&LOG, "Could not find anchor or source constraints in stored override data");
+ CLOG_ERROR(&LOG, "Could not find source constraint in stored override data");
BKE_lib_override_library_property_operation_delete(op, opop);
continue;
}
- bConstraint *constraint_src = constraint_anchor->next;
+
opop->subitem_reference_name = opop->subitem_local_name;
opop->subitem_local_name = BLI_strdup(constraint_src->name);
opop->subitem_reference_index = opop->subitem_local_index;
@@ -1350,13 +1353,15 @@ static void version_liboverride_rnacollections_insertion_object(Object *object)
opop->subitem_local_name,
offsetof(ModifierData, name),
opop->subitem_local_index);
- if (mod_anchor == NULL || mod_anchor->next == NULL) {
+ ModifierData *mod_src = mod_anchor != NULL ? mod_anchor->next : object->modifiers.first;
+
+ if (mod_src == NULL) {
/* Invalid case, just remove that override property operation. */
- CLOG_ERROR(&LOG, "Could not find anchor or source modifiers in stored override data");
+ CLOG_ERROR(&LOG, "Could not find source modifier in stored override data");
BKE_lib_override_library_property_operation_delete(op, opop);
continue;
}
- ModifierData *mod_src = mod_anchor->next;
+
opop->subitem_reference_name = opop->subitem_local_name;
opop->subitem_local_name = BLI_strdup(mod_src->name);
opop->subitem_reference_index = opop->subitem_local_index;
@@ -1375,13 +1380,17 @@ static void version_liboverride_rnacollections_insertion_object(Object *object)
opop->subitem_local_name,
offsetof(GpencilModifierData, name),
opop->subitem_local_index);
- if (gp_mod_anchor == NULL || gp_mod_anchor->next == NULL) {
+ GpencilModifierData *gp_mod_src = gp_mod_anchor != NULL ?
+ gp_mod_anchor->next :
+ object->greasepencil_modifiers.first;
+
+ if (gp_mod_src == NULL) {
/* Invalid case, just remove that override property operation. */
- CLOG_ERROR(&LOG, "Could not find anchor GP modifier in stored override data");
+ CLOG_ERROR(&LOG, "Could not find source GP modifier in stored override data");
BKE_lib_override_library_property_operation_delete(op, opop);
continue;
}
- GpencilModifierData *gp_mod_src = gp_mod_anchor->next;
+
opop->subitem_reference_name = opop->subitem_local_name;
opop->subitem_local_name = BLI_strdup(gp_mod_src->name);
opop->subitem_reference_index = opop->subitem_local_index;
@@ -2182,7 +2191,7 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
if (ntree->type != NTREE_GEOMETRY) {
continue;
}
- version_node_id(ntree, FN_NODE_COMPARE_FLOATS, "FunctionNodeCompareFloats");
+ version_node_id(ntree, FN_NODE_COMPARE, "FunctionNodeCompareFloats");
version_node_id(ntree, GEO_NODE_CAPTURE_ATTRIBUTE, "GeometryNodeCaptureAttribute");
version_node_id(ntree, GEO_NODE_MESH_BOOLEAN, "GeometryNodeMeshBoolean");
version_node_id(ntree, GEO_NODE_FILL_CURVE, "GeometryNodeFillCurve");
@@ -2367,8 +2376,8 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
- /* Special case to handle older in-dev 3.1 files, before change from 3.0 branch gets merged in
- * master. */
+ /* Special case to handle older in-development 3.1 files, before change from 3.0 branch gets
+ * merged in master. */
if (!MAIN_VERSION_ATLEAST(bmain, 300, 42) ||
(bmain->versionfile == 301 && !MAIN_VERSION_ATLEAST(bmain, 301, 3))) {
/* Update LibOverride operations regarding insertions in RNA collections (i.e. modifiers,
@@ -2385,6 +2394,60 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
FOREACH_MAIN_ID_END;
}
+ if (!MAIN_VERSION_ATLEAST(bmain, 301, 4)) {
+ LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
+ if (ntree->type != NTREE_GEOMETRY) {
+ continue;
+ }
+ version_node_id(ntree, GEO_NODE_CURVE_SPLINE_PARAMETER, "GeometryNodeSplineParameter");
+ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
+ if (node->type == GEO_NODE_CURVE_SPLINE_PARAMETER) {
+ version_node_add_socket_if_not_exist(
+ ntree, node, SOCK_OUT, SOCK_INT, PROP_NONE, "Index", "Index");
+ }
+
+ /* Convert float compare into a more general compare node. */
+ if (node->type == FN_NODE_COMPARE) {
+ if (node->storage == NULL) {
+ NodeFunctionCompare *data = (NodeFunctionCompare *)MEM_callocN(
+ sizeof(NodeFunctionCompare), __func__);
+ data->data_type = SOCK_FLOAT;
+ data->operation = node->custom1;
+ strcpy(node->idname, "FunctionNodeCompare");
+ node->update = NODE_UPDATE;
+ node->storage = data;
+ }
+ }
+ }
+ }
+
+ /* Add a toggle for the breadcrumbs overlay in the node editor. */
+ LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ LISTBASE_FOREACH (SpaceLink *, space, &area->spacedata) {
+ if (space->spacetype == SPACE_NODE) {
+ SpaceNode *snode = (SpaceNode *)space;
+ snode->overlay.flag |= SN_OVERLAY_SHOW_PATH;
+ }
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 301, 5)) {
+ LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
+ if (ntree->type != NTREE_GEOMETRY) {
+ continue;
+ }
+ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
+ if (node->type != GEO_NODE_REALIZE_INSTANCES) {
+ continue;
+ }
+ node->custom1 |= GEO_NODE_REALIZE_INSTANCES_LEGACY_BEHAVIOR;
+ }
+ }
+ }
+
/**
* Versioning code until next subversion bump goes here.
*
@@ -2396,5 +2459,21 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
*/
{
/* Keep this block, even when empty. */
+
+ /* Add node storage for map range node. */
+ FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
+ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
+ if (node->type == SH_NODE_MAP_RANGE) {
+ if (node->storage == NULL) {
+ NodeMapRange *data = MEM_callocN(sizeof(NodeMapRange), __func__);
+ data->clamp = node->custom1;
+ data->data_type = CD_PROP_FLOAT;
+ data->interpolation_type = node->custom2;
+ node->storage = data;
+ }
+ }
+ }
+ }
+ FOREACH_NODETREE_END;
}
}
diff --git a/source/blender/blenloader/intern/versioning_common.cc b/source/blender/blenloader/intern/versioning_common.cc
index af765be619f..3deaaa040d6 100644
--- a/source/blender/blenloader/intern/versioning_common.cc
+++ b/source/blender/blenloader/intern/versioning_common.cc
@@ -61,11 +61,6 @@ ARegion *do_versions_add_region_if_not_found(ListBase *regionbase,
return new_region;
}
-/**
- * Rename if the ID doesn't exist.
- *
- * \return the ID (if found).
- */
ID *do_versions_rename_id(Main *bmain,
const short id_type,
const char *name_src,
@@ -104,9 +99,6 @@ static void change_node_socket_name(ListBase *sockets, const char *old_name, con
}
}
-/**
- * Convert `SocketName.001` unique name format to `SocketName_001`. Previously both were used.
- */
void version_node_socket_id_delim(bNodeSocket *socket)
{
StringRef name = socket->name;
@@ -165,9 +157,21 @@ void version_node_output_socket_name(bNodeTree *ntree,
}
}
-/**
- * Replace the ID name of all nodes in the tree with the given type with the new name.
- */
+bNodeSocket *version_node_add_socket_if_not_exist(bNodeTree *ntree,
+ bNode *node,
+ eNodeSocketInOut in_out,
+ int type,
+ int subtype,
+ const char *identifier,
+ const char *name)
+{
+ bNodeSocket *sock = nodeFindSocket(node, in_out, identifier);
+ if (sock != nullptr) {
+ return sock;
+ }
+ return nodeAddStaticSocket(ntree, node, in_out, type, subtype, identifier, name);
+}
+
void version_node_id(bNodeTree *ntree, const int node_type, const char *new_name)
{
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
@@ -179,23 +183,6 @@ void version_node_id(bNodeTree *ntree, const int node_type, const char *new_name
}
}
-/**
- * Adjust animation data for newly added node sockets.
- *
- * Node sockets are addressed by their index (in their RNA path, and thus FCurves/drivers), and
- * thus when a new node is added in the middle of the list, existing animation data needs to be
- * adjusted.
- *
- * Since this is about animation data, it only concerns input sockets.
- *
- * \param node_tree_type node tree type that has these nodes, for example NTREE_SHADER.
- * \param node_type node type to adjust, for example SH_NODE_BSDF_PRINCIPLED.
- * \param socket_index_orig the original index of the moved socket; when socket 4 moved to 6,
- * pass 4 here.
- * \param socket_index_offset the offset of the nodes, so when socket 4 moved to 6,
- * pass 2 here.
- * \param total_number_of_sockets the total number of sockets in the node.
- */
void version_node_socket_index_animdata(Main *bmain,
const int node_tree_type,
const int node_type,
diff --git a/source/blender/blenloader/intern/versioning_common.h b/source/blender/blenloader/intern/versioning_common.h
index 7f179800ddd..0613484b754 100644
--- a/source/blender/blenloader/intern/versioning_common.h
+++ b/source/blender/blenloader/intern/versioning_common.h
@@ -34,6 +34,11 @@ struct ARegion *do_versions_add_region_if_not_found(struct ListBase *regionbase,
const char *name,
int link_after_region_type);
+/**
+ * Rename if the ID doesn't exist.
+ *
+ * \return the ID (if found).
+ */
ID *do_versions_rename_id(Main *bmain,
const short id_type,
const char *name_src,
@@ -52,6 +57,23 @@ void version_node_output_socket_name(struct bNodeTree *ntree,
const char *old_name,
const char *new_name);
+/**
+ * Adjust animation data for newly added node sockets.
+ *
+ * Node sockets are addressed by their index (in their RNA path, and thus FCurves/drivers), and
+ * thus when a new node is added in the middle of the list, existing animation data needs to be
+ * adjusted.
+ *
+ * Since this is about animation data, it only concerns input sockets.
+ *
+ * \param node_tree_type: Node tree type that has these nodes, for example #NTREE_SHADER.
+ * \param node_type: Node type to adjust, for example #SH_NODE_BSDF_PRINCIPLED.
+ * \param socket_index_orig: The original index of the moved socket; when socket 4 moved to 6,
+ * pass 4 here.
+ * \param socket_index_offset: The offset of the nodes, so when socket 4 moved to 6,
+ * pass 2 here.
+ * \param total_number_of_sockets: The total number of sockets in the node.
+ */
void version_node_socket_index_animdata(
Main *bmain,
int node_tree_type, /* NTREE_....., e.g. NTREE_SHADER */
@@ -60,10 +82,24 @@ void version_node_socket_index_animdata(
int socket_index_offset,
int total_number_of_sockets);
+/**
+ * Replace the ID name of all nodes in the tree with the given type with the new name.
+ */
void version_node_id(struct bNodeTree *ntree, const int node_type, const char *new_name);
+/**
+ * Convert `SocketName.001` unique name format to `SocketName_001`. Previously both were used.
+ */
void version_node_socket_id_delim(bNodeSocket *socket);
+struct bNodeSocket *version_node_add_socket_if_not_exist(struct bNodeTree *ntree,
+ struct bNode *node,
+ eNodeSocketInOut in_out,
+ int type,
+ int subtype,
+ const char *identifier,
+ const char *name);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c
index fa61b1ca6cd..a5c44ea711b 100644
--- a/source/blender/blenloader/intern/versioning_defaults.c
+++ b/source/blender/blenloader/intern/versioning_defaults.c
@@ -367,15 +367,6 @@ static void blo_update_defaults_scene(Main *bmain, Scene *scene)
}
}
-/**
- * Update defaults in startup.blend, without having to save and embed the file.
- * This function can be emptied each time the startup.blend is updated.
- *
- * \note Screen data may be cleared at this point, this will happen in the case
- * an app-template's data needs to be versioned when read-file is called with "Load UI" disabled.
- * Versioning the screen data can be safely skipped without "Load UI" since the screen data
- * will have been versioned when it was first loaded.
- */
void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template)
{
/* For all app templates. */
diff --git a/source/blender/blenloader/intern/versioning_dna.c b/source/blender/blenloader/intern/versioning_dna.c
index aee54b94833..0a97eedb993 100644
--- a/source/blender/blenloader/intern/versioning_dna.c
+++ b/source/blender/blenloader/intern/versioning_dna.c
@@ -29,16 +29,6 @@
#include "BLO_readfile.h"
#include "readfile.h"
-/**
- * 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, const int versionfile, const int subversionfile)
{
#define DNA_VERSION_ATLEAST(ver, subver) \
diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c
index 37bf4898cb3..2fceb42262e 100644
--- a/source/blender/blenloader/intern/versioning_legacy.c
+++ b/source/blender/blenloader/intern/versioning_legacy.c
@@ -461,8 +461,6 @@ static void do_version_constraints_245(ListBase *lb)
}
}
-/* 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)
{
/* create new trackto constraint from the relationship */
diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c
index 0e5e0b76f43..3338d2f658c 100644
--- a/source/blender/blenloader/intern/versioning_userdef.c
+++ b/source/blender/blenloader/intern/versioning_userdef.c
@@ -399,7 +399,6 @@ static bool keymap_item_has_invalid_wm_context_data_path(wmKeyMapItem *kmi,
return false;
}
-/* patching UserDef struct and Themes */
void blo_do_versions_userdef(UserDef *userdef)
{
/* #UserDef & #Main happen to have the same struct member. */
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 56ff7151cb1..aa3eef4b475 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -50,7 +50,7 @@
* Almost all data in Blender are structures. Each struct saved
* gets a BHead header. With BHead the struct can be linked again
* and compared with #StructDNA.
-
+ *
* WRITE
* =====
*
@@ -1028,7 +1028,7 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar)
/* prevent mem checkers from complaining */
memset(fg._pad, 0, sizeof(fg._pad));
- memset(fg.filename, 0, sizeof(fg.filename));
+ memset(fg.filepath, 0, sizeof(fg.filepath));
memset(fg.build_hash, 0, sizeof(fg.build_hash));
fg._pad1 = NULL;
@@ -1045,7 +1045,7 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar)
fg.globalf = G.f;
/* Write information needed for recovery. */
if (fileflags & G_FILE_RECOVER_WRITE) {
- BLI_strncpy(fg.filename, mainvar->name, sizeof(fg.filename));
+ STRNCPY(fg.filepath, mainvar->filepath);
}
sprintf(subvstr, "%4d", BLENDER_FILE_SUBVERSION);
memcpy(fg.subvstr, subvstr, 4);
@@ -1312,15 +1312,15 @@ static bool do_history(const char *name, ReportList *reports)
/** \name File Writing (Public)
* \{ */
-/**
- * \return Success.
- */
bool BLO_write_file(Main *mainvar,
const char *filepath,
const int write_flags,
const struct BlendFileWriteParams *params,
ReportList *reports)
{
+ BLI_assert(!BLI_path_is_rel(filepath));
+ BLI_assert(BLI_path_is_abs_from_cwd(filepath));
+
char tempname[FILE_MAX + 1];
WriteWrap ww;
@@ -1329,10 +1329,12 @@ bool BLO_write_file(Main *mainvar,
const bool use_save_as_copy = params->use_save_as_copy;
const bool use_userdef = params->use_userdef;
const BlendThumbnail *thumb = params->thumb;
+ const bool relbase_valid = (mainvar->filepath[0] != '\0');
/* path backup/restore */
void *path_list_backup = NULL;
- const int path_list_flag = (BKE_BPATH_TRAVERSE_SKIP_LIBRARY | BKE_BPATH_TRAVERSE_SKIP_MULTIFILE);
+ const eBPathForeachFlag path_list_flag = (BKE_BPATH_FOREACH_PATH_SKIP_LINKED |
+ BKE_BPATH_FOREACH_PATH_SKIP_MULTIFILE);
if (G.debug & G_DEBUG_IO && mainvar->lock != NULL) {
BKE_report(reports, RPT_INFO, "Checking sanity of current .blend file *BEFORE* save to disk");
@@ -1351,35 +1353,47 @@ bool BLO_write_file(Main *mainvar,
return 0;
}
+ if (remap_mode == BLO_WRITE_PATH_REMAP_ABSOLUTE) {
+ /* Paths will already be absolute, no remapping to do. */
+ if (relbase_valid == false) {
+ remap_mode = BLO_WRITE_PATH_REMAP_NONE;
+ }
+ }
+
/* Remapping of relative paths to new file location. */
if (remap_mode != BLO_WRITE_PATH_REMAP_NONE) {
if (remap_mode == BLO_WRITE_PATH_REMAP_RELATIVE) {
- /* Make all relative as none of the existing paths can be relative in an unsaved document.
- */
- if (G.relbase_valid == false) {
+ /* Make all relative as none of the existing paths can be relative in an unsaved document. */
+ if (relbase_valid == false) {
remap_mode = BLO_WRITE_PATH_REMAP_RELATIVE_ALL;
}
}
+ /* The source path only makes sense to set if the file was saved (`relbase_valid`). */
char dir_src[FILE_MAX];
char dir_dst[FILE_MAX];
- BLI_split_dir_part(mainvar->name, dir_src, sizeof(dir_src));
- BLI_split_dir_part(filepath, dir_dst, sizeof(dir_dst));
- /* Just in case there is some subtle difference. */
- BLI_path_normalize(mainvar->name, dir_dst);
- BLI_path_normalize(mainvar->name, dir_src);
+ /* Normalize the paths in case there is some subtle difference (so they can be compared). */
+ if (relbase_valid) {
+ BLI_split_dir_part(mainvar->filepath, dir_src, sizeof(dir_src));
+ BLI_path_normalize(NULL, dir_src);
+ }
+ else {
+ dir_src[0] = '\0';
+ }
+ BLI_split_dir_part(filepath, dir_dst, sizeof(dir_dst));
+ BLI_path_normalize(NULL, dir_dst);
/* Only for relative, not relative-all, as this means making existing paths relative. */
if (remap_mode == BLO_WRITE_PATH_REMAP_RELATIVE) {
- if (G.relbase_valid && (BLI_path_cmp(dir_dst, dir_src) == 0)) {
+ if (relbase_valid && (BLI_path_cmp(dir_dst, dir_src) == 0)) {
/* Saved to same path. Nothing to do. */
remap_mode = BLO_WRITE_PATH_REMAP_NONE;
}
}
else if (remap_mode == BLO_WRITE_PATH_REMAP_ABSOLUTE) {
- if (G.relbase_valid == false) {
+ if (relbase_valid == false) {
/* Unsaved, all paths are absolute.Even if the user manages to set a relative path,
* there is no base-path that can be used to make it absolute. */
remap_mode = BLO_WRITE_PATH_REMAP_NONE;
@@ -1395,6 +1409,7 @@ bool BLO_write_file(Main *mainvar,
switch (remap_mode) {
case BLO_WRITE_PATH_REMAP_RELATIVE:
/* Saved, make relative paths relative to new location (if possible). */
+ BLI_assert(relbase_valid);
BKE_bpath_relative_rebase(mainvar, dir_src, dir_dst, NULL);
break;
case BLO_WRITE_PATH_REMAP_RELATIVE_ALL:
@@ -1403,6 +1418,7 @@ bool BLO_write_file(Main *mainvar,
break;
case BLO_WRITE_PATH_REMAP_ABSOLUTE:
/* Make all absolute (when requested or unsaved). */
+ BLI_assert(relbase_valid);
BKE_bpath_absolute_convert(mainvar, dir_src, NULL);
break;
case BLO_WRITE_PATH_REMAP_NONE:
@@ -1452,9 +1468,6 @@ bool BLO_write_file(Main *mainvar,
return 1;
}
-/**
- * \return Success.
- */
bool BLO_write_file_mem(Main *mainvar, MemFile *compare, MemFile *current, int write_flags)
{
bool use_userdef = false;
@@ -1577,9 +1590,6 @@ void BLO_write_float3_array(BlendWriter *writer, uint num, const float *data_ptr
BLO_write_raw(writer, sizeof(float[3]) * (size_t)num, data_ptr);
}
-/**
- * Write a null terminated string.
- */
void BLO_write_string(BlendWriter *writer, const char *data_ptr)
{
if (data_ptr != NULL) {
@@ -1587,10 +1597,6 @@ void BLO_write_string(BlendWriter *writer, const char *data_ptr)
}
}
-/**
- * Sometimes different data is written depending on whether the file is saved to disk or used for
- * undo. This function returns true when the current file-writing is done for undo.
- */
bool BLO_write_is_undo(BlendWriter *writer)
{
return writer->wd->use_memfile;