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:
-rw-r--r--source/blender/blenkernel/BKE_blendfile.h1
-rw-r--r--source/blender/blenkernel/BKE_global.h7
-rw-r--r--source/blender/blenkernel/intern/blender_copybuffer.c5
-rw-r--r--source/blender/blenkernel/intern/blender_undo.c2
-rw-r--r--source/blender/blenkernel/intern/blendfile.c11
-rw-r--r--source/blender/blenloader/BLO_writefile.h27
-rw-r--r--source/blender/blenloader/intern/writefile.c73
-rw-r--r--source/blender/python/intern/bpy_library_write.c41
-rw-r--r--source/blender/windowmanager/intern/wm_files.c24
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c2
10 files changed, 139 insertions, 54 deletions
diff --git a/source/blender/blenkernel/BKE_blendfile.h b/source/blender/blenkernel/BKE_blendfile.h
index 2bff684948d..e835137bfa1 100644
--- a/source/blender/blenkernel/BKE_blendfile.h
+++ b/source/blender/blenkernel/BKE_blendfile.h
@@ -74,6 +74,7 @@ void BKE_blendfile_write_partial_begin(struct Main *bmain_src);
bool BKE_blendfile_write_partial(struct Main *bmain_src,
const char *filepath,
const int write_flags,
+ const int remap_mode,
struct ReportList *reports);
void BKE_blendfile_write_partial_end(struct Main *bmain_src);
diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h
index a1871d22da7..a134f29228f 100644
--- a/source/blender/blenkernel/BKE_global.h
+++ b/source/blender/blenkernel/BKE_global.h
@@ -177,13 +177,11 @@ enum {
/** On read, use #FileGlobal.filename instead of the real location on-disk,
* needed for recovering temp files so relative paths resolve */
G_FILE_RECOVER = (1 << 23),
- /** On write, remap relative file paths to the new file location. */
- G_FILE_RELATIVE_REMAP = (1 << 24),
/** On write, make backup `.blend1`, `.blend2` ... files, when the users preference is enabled */
G_FILE_HISTORY = (1 << 25),
/** BMesh option to save as older mesh format */
/* #define G_FILE_MESH_COMPAT (1 << 26) */
- /** On write, restore paths after editing them (G_FILE_RELATIVE_REMAP) */
+ /** On write, restore paths after editing them (see #BLO_WRITE_PATH_REMAP_RELATIVE). */
G_FILE_SAVE_COPY = (1 << 27),
/* #define G_FILE_GLSL_NO_ENV_LIGHTING (1 << 28) */ /* deprecated */
};
@@ -192,8 +190,7 @@ enum {
* Run-time only #G.fileflags which are never read or written to/from Blend files.
* This means we can change the values without worrying about do-versions.
*/
-#define G_FILE_FLAG_ALL_RUNTIME \
- (G_FILE_NO_UI | G_FILE_RELATIVE_REMAP | G_FILE_HISTORY | G_FILE_SAVE_COPY)
+#define G_FILE_FLAG_ALL_RUNTIME (G_FILE_NO_UI | G_FILE_HISTORY | G_FILE_SAVE_COPY)
/** ENDIAN_ORDER: indicates what endianness the platform where the file was written had. */
#if !defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)
diff --git a/source/blender/blenkernel/intern/blender_copybuffer.c b/source/blender/blenkernel/intern/blender_copybuffer.c
index 4d27621a861..bd133ce9ea6 100644
--- a/source/blender/blenkernel/intern/blender_copybuffer.c
+++ b/source/blender/blenkernel/intern/blender_copybuffer.c
@@ -72,9 +72,10 @@ void BKE_copybuffer_tag_ID(ID *id)
*/
bool BKE_copybuffer_save(Main *bmain_src, const char *filename, ReportList *reports)
{
- const int write_flags = G_FILE_RELATIVE_REMAP;
+ const int write_flags = 0;
+ const eBLO_WritePathRemap remap_mode = BLO_WRITE_PATH_REMAP_RELATIVE;
- bool retval = BKE_blendfile_write_partial(bmain_src, filename, write_flags, reports);
+ bool retval = BKE_blendfile_write_partial(bmain_src, filename, write_flags, remap_mode, reports);
BKE_blendfile_write_partial_end(bmain_src);
diff --git a/source/blender/blenkernel/intern/blender_undo.c b/source/blender/blenkernel/intern/blender_undo.c
index c8aff345487..e19a4935698 100644
--- a/source/blender/blenkernel/intern/blender_undo.c
+++ b/source/blender/blenkernel/intern/blender_undo.c
@@ -119,7 +119,7 @@ MemFileUndoData *BKE_memfile_undo_encode(Main *bmain, MemFileUndoData *mfu_prev)
BLI_snprintf(numstr, sizeof(numstr), "%d.blend", counter);
BLI_join_dirfile(filename, sizeof(filename), BKE_tempdir_session(), numstr);
- /* success = */ /* UNUSED */ BLO_write_file(bmain, filename, fileflags, NULL, NULL);
+ /* success = */ /* UNUSED */ BLO_write_file(bmain, filename, fileflags, NULL);
BLI_strncpy(mfu->filename, filename, sizeof(mfu->filename));
}
diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c
index ef474022f19..a3031e9047f 100644
--- a/source/blender/blenkernel/intern/blendfile.c
+++ b/source/blender/blenkernel/intern/blendfile.c
@@ -646,7 +646,7 @@ bool BKE_blendfile_userdef_write(const char *filepath, ReportList *reports)
Main *mainb = MEM_callocN(sizeof(Main), "empty main");
bool ok = false;
- if (BLO_write_file(mainb, filepath, G_FILE_USERPREFS, reports, NULL)) {
+ if (BLO_write_file(mainb, filepath, G_FILE_USERPREFS, reports)) {
ok = true;
}
@@ -777,7 +777,8 @@ bool BKE_blendfile_workspace_config_write(Main *bmain, const char *filepath, Rep
BKE_blendfile_write_partial_tag_ID(&workspace->id, true);
}
- if (BKE_blendfile_write_partial(bmain, filepath, fileflags, reports)) {
+ if (BKE_blendfile_write_partial(
+ bmain, filepath, fileflags, BLO_WRITE_PATH_REMAP_NONE, reports)) {
retval = true;
}
@@ -829,11 +830,13 @@ static void blendfile_write_partial_cb(void *UNUSED(handle), Main *UNUSED(bmain)
}
/**
+ * \param remap_mode: Choose the kind of path remapping or none #eBLO_FilePathRemap.
* \return Success.
*/
bool BKE_blendfile_write_partial(Main *bmain_src,
const char *filepath,
const int write_flags,
+ const int remap_mode,
ReportList *reports)
{
Main *bmain_dst = MEM_callocN(sizeof(Main), "copybuffer");
@@ -875,12 +878,12 @@ bool BKE_blendfile_write_partial(Main *bmain_src,
* This happens because id_sort_by_name does not take into account
* string case or the library name, so the order is not strictly
* defined for two linked data-blocks with the same name! */
- if (write_flags & G_FILE_RELATIVE_REMAP) {
+ if (remap_mode != BLO_WRITE_PATH_REMAP_NONE) {
path_list_backup = BKE_bpath_list_backup(bmain_dst, path_list_flag);
}
/* save the buffer */
- retval = BLO_write_file(bmain_dst, filepath, write_flags, reports, NULL);
+ retval = BLO_write_file_ex(bmain_dst, filepath, write_flags, reports, remap_mode, NULL);
if (path_list_backup) {
BKE_bpath_list_restore(bmain_dst, path_list_flag, path_list_backup);
diff --git a/source/blender/blenloader/BLO_writefile.h b/source/blender/blenloader/BLO_writefile.h
index d83abf7f9ed..18783474392 100644
--- a/source/blender/blenloader/BLO_writefile.h
+++ b/source/blender/blenloader/BLO_writefile.h
@@ -30,11 +30,32 @@ struct Main;
struct MemFile;
struct ReportList;
+/**
+ * Adjust paths when saving (kept unless #G_FILE_SAVE_COPY is set).
+ */
+typedef enum eBLO_WritePathRemap {
+ /** No path manipulation. */
+ BLO_WRITE_PATH_REMAP_NONE = 1,
+ /** Remap existing relative paths (default). */
+ BLO_WRITE_PATH_REMAP_RELATIVE = 2,
+ /** Remap paths making all paths relative to the new location. */
+ BLO_WRITE_PATH_REMAP_RELATIVE_ALL = 3,
+ /** Make all paths absolute. */
+ BLO_WRITE_PATH_REMAP_ABSOLUTE = 4,
+} eBLO_WritePathRemap;
+
+extern bool BLO_write_file_ex(struct Main *mainvar,
+ const char *filepath,
+ const int write_flags,
+ struct ReportList *reports,
+ /* Extra arguments. */
+ eBLO_WritePathRemap remap_mode,
+ const struct BlendThumbnail *thumb);
extern bool BLO_write_file(struct Main *mainvar,
const char *filepath,
- int write_flags,
- struct ReportList *reports,
- const struct BlendThumbnail *thumb);
+ const int write_flags,
+ struct ReportList *reports);
+
extern bool BLO_write_file_mem(struct Main *mainvar,
struct MemFile *compare,
struct MemFile *current,
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index a40cc4c3ad2..1cda22de941 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -4400,11 +4400,13 @@ static bool do_history(const char *name, ReportList *reports)
/**
* \return Success.
*/
-bool BLO_write_file(Main *mainvar,
- const char *filepath,
- int write_flags,
- ReportList *reports,
- const BlendThumbnail *thumb)
+bool BLO_write_file_ex(Main *mainvar,
+ const char *filepath,
+ const int write_flags,
+ ReportList *reports,
+ /* Extra arguments. */
+ eBLO_WritePathRemap remap_mode,
+ const BlendThumbnail *thumb)
{
char tempname[FILE_MAX + 1];
eWriteWrapType ww_type;
@@ -4439,7 +4441,15 @@ bool BLO_write_file(Main *mainvar,
}
/* Remapping of relative paths to new file location. */
- if (write_flags & G_FILE_RELATIVE_REMAP) {
+ 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) {
+ remap_mode = BLO_WRITE_PATH_REMAP_RELATIVE_ALL;
+ }
+ }
+
char dir_src[FILE_MAX];
char dir_dst[FILE_MAX];
BLI_split_dir_part(mainvar->name, dir_src, sizeof(dir_src));
@@ -4449,23 +4459,43 @@ bool BLO_write_file(Main *mainvar,
BLI_path_normalize(mainvar->name, dir_dst);
BLI_path_normalize(mainvar->name, dir_src);
- if (G.relbase_valid && (BLI_path_cmp(dir_dst, dir_src) == 0)) {
- /* Saved to same path. Nothing to do. */
- write_flags &= ~G_FILE_RELATIVE_REMAP;
+ /* 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)) {
+ /* Saved to same path. Nothing to do. */
+ remap_mode = BLO_WRITE_PATH_REMAP_NONE;
+ }
}
- else {
+ else if (remap_mode == BLO_WRITE_PATH_REMAP_ABSOLUTE) {
+ if (G.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;
+ }
+ }
+
+ if (remap_mode != BLO_WRITE_PATH_REMAP_NONE) {
/* Check if we need to backup and restore paths. */
if (UNLIKELY(G_FILE_SAVE_COPY & write_flags)) {
path_list_backup = BKE_bpath_list_backup(mainvar, path_list_flag);
}
- if (G.relbase_valid) {
- /* Saved, make relative paths relative to new location (if possible). */
- BKE_bpath_relative_rebase(mainvar, dir_src, dir_dst, NULL);
- }
- else {
- /* Unsaved, make all relative. */
- BKE_bpath_relative_convert(mainvar, dir_dst, NULL);
+ switch (remap_mode) {
+ case BLO_WRITE_PATH_REMAP_RELATIVE:
+ /* Saved, make relative paths relative to new location (if possible). */
+ BKE_bpath_relative_rebase(mainvar, dir_src, dir_dst, NULL);
+ break;
+ case BLO_WRITE_PATH_REMAP_RELATIVE_ALL:
+ /* Make all relative (when requested or unsaved). */
+ BKE_bpath_relative_convert(mainvar, dir_dst, NULL);
+ break;
+ case BLO_WRITE_PATH_REMAP_ABSOLUTE:
+ /* Make all absolute (when requested or unsaved). */
+ BKE_bpath_absolute_convert(mainvar, dir_src, NULL);
+ break;
+ case BLO_WRITE_PATH_REMAP_NONE:
+ BLI_assert(0); /* Unreachable. */
+ break;
}
}
}
@@ -4510,6 +4540,15 @@ bool BLO_write_file(Main *mainvar,
return 1;
}
+bool BLO_write_file(Main *mainvar,
+ const char *filepath,
+ const int write_flags,
+ ReportList *reports)
+{
+ return BLO_write_file_ex(
+ mainvar, filepath, write_flags, reports, BLO_WRITE_PATH_REMAP_NONE, NULL);
+}
+
/**
* \return Success.
*/
diff --git a/source/blender/python/intern/bpy_library_write.c b/source/blender/python/intern/bpy_library_write.c
index fec0cef7b05..66d20dd357f 100644
--- a/source/blender/python/intern/bpy_library_write.c
+++ b/source/blender/python/intern/bpy_library_write.c
@@ -35,6 +35,8 @@
#include "BKE_main.h"
#include "BKE_report.h"
+#include "BLO_writefile.h"
+
#include "RNA_types.h"
#include "bpy_capi_utils.h"
@@ -45,8 +47,7 @@
PyDoc_STRVAR(
bpy_lib_write_doc,
- ".. method:: write(filepath, datablocks, relative_remap=False, fake_user=False, "
- "compress=False)\n"
+ ".. method:: write(filepath, datablocks, path_remap=False, fake_user=False, compress=False)\n"
"\n"
" Write data-blocks into a blend file.\n"
"\n"
@@ -58,8 +59,14 @@ PyDoc_STRVAR(
" :type filepath: string\n"
" :arg datablocks: set of data-blocks (:class:`bpy.types.ID` instances).\n"
" :type datablocks: set\n"
- " :arg relative_remap: When True, make paths relative to the current blend-file.\n"
- " :type relative_remap: bool\n"
+ " :arg path_remap: Optionally remap paths when writing the file:\n"
+ "\n"
+ " - ``NONE`` No path manipulation (default).\n"
+ " - ``RELATIVE`` Remap paths that are already relative to the new location.\n"
+ " - ``RELATIVE_ALL`` Remap all paths to be relative to the new location.\n"
+ " - ``ABSOLUTE`` Make all paths absolute on writing.\n"
+ "\n"
+ " :type path_remap: string\n"
" :arg fake_user: When True, data-blocks will be written with fake-user flag enabled.\n"
" :type fake_user: bool\n"
" :arg compress: When True, write a compressed blend file.\n"
@@ -70,13 +77,23 @@ static PyObject *bpy_lib_write(PyObject *UNUSED(self), PyObject *args, PyObject
const char *filepath;
char filepath_abs[FILE_MAX];
PyObject *datablocks = NULL;
- bool use_relative_remap = false, use_fake_user = false, use_compress = false;
+
+ const struct PyC_StringEnumItems path_remap_items[] = {
+ {BLO_WRITE_PATH_REMAP_NONE, "NONE"},
+ {BLO_WRITE_PATH_REMAP_RELATIVE, "RELATIVE"},
+ {BLO_WRITE_PATH_REMAP_RELATIVE_ALL, "RELATIVE_ALL"},
+ {BLO_WRITE_PATH_REMAP_ABSOLUTE, "ABSOLUTE"},
+ {0, NULL},
+ };
+ struct PyC_StringEnum path_remap = {path_remap_items, BLO_WRITE_PATH_REMAP_NONE};
+
+ bool use_fake_user = false, use_compress = false;
static const char *_keywords[] = {
"filepath",
"datablocks",
/* optional */
- "relative_remap",
+ "path_remap",
"fake_user",
"compress",
NULL,
@@ -88,8 +105,8 @@ static PyObject *bpy_lib_write(PyObject *UNUSED(self), PyObject *args, PyObject
&filepath,
&PySet_Type,
&datablocks,
- PyC_ParseBool,
- &use_relative_remap,
+ PyC_ParseStringEnum,
+ &path_remap,
PyC_ParseBool,
&use_fake_user,
PyC_ParseBool,
@@ -100,10 +117,6 @@ static PyObject *bpy_lib_write(PyObject *UNUSED(self), PyObject *args, PyObject
Main *bmain_src = G_MAIN;
int write_flags = 0;
- if (use_relative_remap) {
- write_flags |= G_FILE_RELATIVE_REMAP;
- }
-
if (use_compress) {
write_flags |= G_FILE_COMPRESS;
}
@@ -162,8 +175,8 @@ static PyObject *bpy_lib_write(PyObject *UNUSED(self), PyObject *args, PyObject
ReportList reports;
BKE_reports_init(&reports, RPT_STORE);
-
- retval = BKE_blendfile_write_partial(bmain_src, filepath_abs, write_flags, &reports);
+ retval = BKE_blendfile_write_partial(
+ bmain_src, filepath_abs, write_flags, path_remap.value_found, &reports);
/* cleanup state */
BKE_blendfile_write_partial_end(bmain_src);
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 1ecfbfb4b8d..b2753886f69 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -1409,7 +1409,7 @@ bool write_crash_blend(void)
BLI_strncpy(path, BKE_main_blendfile_path_from_global(), sizeof(path));
BLI_path_extension_replace(path, sizeof(path), "_crash.blend");
- if (BLO_write_file(G_MAIN, path, fileflags, NULL, NULL)) {
+ if (BLO_write_file(G_MAIN, path, fileflags, NULL)) {
printf("written: %s\n", path);
return 1;
}
@@ -1422,7 +1422,11 @@ bool write_crash_blend(void)
/**
* \see #wm_homefile_write_exec wraps #BLO_write_file in a similar way.
*/
-static bool wm_file_write(bContext *C, const char *filepath, int fileflags, ReportList *reports)
+static bool wm_file_write(bContext *C,
+ const char *filepath,
+ int fileflags,
+ eBLO_WritePathRemap remap_mode,
+ ReportList *reports)
{
Main *bmain = CTX_data_main(C);
Library *li;
@@ -1499,7 +1503,7 @@ static bool wm_file_write(bContext *C, const char *filepath, int fileflags, Repo
/* XXX temp solution to solve bug, real fix coming (ton) */
bmain->recovered = 0;
- if (BLO_write_file(CTX_data_main(C), filepath, fileflags, reports, thumb)) {
+ if (BLO_write_file_ex(CTX_data_main(C), filepath, fileflags, reports, remap_mode, thumb)) {
const bool do_history = (G.background == false) && (CTX_wm_manager(C)->op_undo_depth == 0);
if (!(fileflags & G_FILE_SAVE_COPY)) {
@@ -1632,7 +1636,7 @@ void wm_autosave_timer(Main *bmain, wmWindowManager *wm, wmTimer *UNUSED(wt))
ED_editors_flush_edits(bmain);
/* Error reporting into console */
- BLO_write_file(bmain, filepath, fileflags, NULL, NULL);
+ BLO_write_file(bmain, filepath, fileflags, NULL);
}
/* do timer after file write, just in case file write takes a long time */
wm->autosavetimer = WM_event_add_timer(wm, NULL, TIMERAUTOSAVE, U.savetime * 60.0);
@@ -1752,7 +1756,8 @@ static int wm_homefile_write_exec(bContext *C, wmOperator *op)
/* Force save as regular blend file. */
fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_HISTORY);
- if (BLO_write_file(bmain, filepath, fileflags, op->reports, NULL) == 0) {
+ if (BLO_write_file_ex(
+ bmain, filepath, fileflags, op->reports, BLO_WRITE_PATH_REMAP_RELATIVE, NULL) == 0) {
printf("fail\n");
return OPERATOR_CANCELLED;
}
@@ -2668,6 +2673,12 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op)
char path[FILE_MAX];
const bool is_save_as = (op->type->invoke == wm_save_as_mainfile_invoke);
+ /* We could expose all options to the users however in most cases remapping
+ * existing relative paths is a good default.
+ * Users can manually make their paths relative & absolute if they wish. */
+ const eBLO_WritePathRemap remap_mode = RNA_boolean_get(op->ptr, "relative_remap") ?
+ BLO_WRITE_PATH_REMAP_RELATIVE :
+ BLO_WRITE_PATH_REMAP_NONE;
save_set_compress(op);
if (RNA_struct_property_is_set(op->ptr, "filepath")) {
@@ -2683,13 +2694,12 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op)
/* set compression flag */
SET_FLAG_FROM_TEST(fileflags, RNA_boolean_get(op->ptr, "compress"), G_FILE_COMPRESS);
- SET_FLAG_FROM_TEST(fileflags, RNA_boolean_get(op->ptr, "relative_remap"), G_FILE_RELATIVE_REMAP);
SET_FLAG_FROM_TEST(
fileflags,
(RNA_struct_property_is_set(op->ptr, "copy") && RNA_boolean_get(op->ptr, "copy")),
G_FILE_SAVE_COPY);
- const bool ok = wm_file_write(C, path, fileflags, op->reports);
+ const bool ok = wm_file_write(C, path, fileflags, remap_mode, op->reports);
if ((op->flag & OP_IS_INVOKE) == 0) {
/* OP_IS_INVOKE is set when the operator is called from the GUI.
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 001acc459c2..27aa9c532e5 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -500,7 +500,7 @@ void WM_exit_ex(bContext *C, const bool do_python)
has_edited = ED_editors_flush_edits(bmain);
- if ((has_edited && BLO_write_file(bmain, filename, fileflags, NULL, NULL)) ||
+ if ((has_edited && BLO_write_file(bmain, filename, fileflags, NULL)) ||
(undo_memfile && BLO_memfile_write_file(undo_memfile, filename))) {
printf("Saved session recovery to '%s'\n", filename);
}