WM: explicitly skip auto-save when in modes that don't support it
Auto-save currently only really works in modes that use the `MemFile` undo step, that excludes things like mesh edit and sculpt mode. Previously, Blender would attempt to auto-save in those modes, but it would only save the last state from before the mode was entered, which is useless when staying in the mode for longer. This problem is *not* fixed here. However, the code now explicitly skips auto-saving in order to avoid unnecessary short freezes in these modes when Blender auto-saves. Furthermore, the auto-save will now happen when changing modes. This reduces the impact of save-time-regressions with #106903. Pull Request: https://projects.blender.org/blender/blender/pulls/118892
This commit is contained in:
@@ -129,7 +129,7 @@ void ED_undosys_type_free();
|
||||
|
||||
/* `memfile_undo.cc` */
|
||||
|
||||
MemFile *ED_undosys_stack_memfile_get_active(UndoStack *ustack);
|
||||
MemFile *ED_undosys_stack_memfile_get_if_active(UndoStack *ustack);
|
||||
/**
|
||||
* If the last undo step is a memfile one, find the first #MemFileChunk matching given ID
|
||||
* (using its session UUID), and tag it as "changed in the future".
|
||||
|
||||
@@ -1862,6 +1862,13 @@ static int object_mode_set_exec(bContext *C, wmOperator *op)
|
||||
}
|
||||
}
|
||||
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
if (wm) {
|
||||
if (WM_autosave_is_scheduled(wm)) {
|
||||
WM_autosave_write(wm, CTX_data_main(C));
|
||||
}
|
||||
}
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
|
||||
@@ -355,13 +355,15 @@ static MemFile *ed_undosys_step_get_memfile(UndoStep *us_p)
|
||||
return &us->data->memfile;
|
||||
}
|
||||
|
||||
MemFile *ED_undosys_stack_memfile_get_active(UndoStack *ustack)
|
||||
MemFile *ED_undosys_stack_memfile_get_if_active(UndoStack *ustack)
|
||||
{
|
||||
UndoStep *us = BKE_undosys_stack_active_with_type(ustack, BKE_UNDOSYS_TYPE_MEMFILE);
|
||||
if (us) {
|
||||
return ed_undosys_step_get_memfile(us);
|
||||
if (!ustack->step_active) {
|
||||
return nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
if (ustack->step_active->type != BKE_UNDOSYS_TYPE_MEMFILE) {
|
||||
return nullptr;
|
||||
}
|
||||
return ed_undosys_step_get_memfile(ustack->step_active);
|
||||
}
|
||||
|
||||
void ED_undosys_stack_memfile_id_changed_tag(UndoStack *ustack, ID *id)
|
||||
|
||||
@@ -210,6 +210,9 @@ typedef struct wmWindowManager {
|
||||
ListBase timers;
|
||||
/** Timer for auto save. */
|
||||
struct wmTimer *autosavetimer;
|
||||
/** Auto-save timer was up, but it wasn't possible to auto-save in the current mode. */
|
||||
char autosave_scheduled;
|
||||
char _pad2[7];
|
||||
|
||||
/** All undo history (runtime only). */
|
||||
struct UndoStack *undo_stack;
|
||||
|
||||
@@ -1720,6 +1720,10 @@ void WM_main_playanim(int argc, const char **argv);
|
||||
*/
|
||||
bool write_crash_blend();
|
||||
|
||||
bool WM_autosave_is_scheduled(wmWindowManager *wm);
|
||||
/** Flushes all changes from edit modes and stores the auto-save file. */
|
||||
void WM_autosave_write(wmWindowManager *wm, Main *bmain);
|
||||
|
||||
/**
|
||||
* Lock the interface for any communication.
|
||||
*/
|
||||
|
||||
@@ -2109,33 +2109,48 @@ static void wm_autosave_location(char filepath[FILE_MAX])
|
||||
BLI_path_join(filepath, FILE_MAX, tempdir_base, filename);
|
||||
}
|
||||
|
||||
static void wm_autosave_write(Main *bmain, wmWindowManager *wm)
|
||||
static bool wm_autosave_write_try(Main *bmain, wmWindowManager *wm)
|
||||
{
|
||||
char filepath[FILE_MAX];
|
||||
|
||||
wm_autosave_location(filepath);
|
||||
|
||||
/* Fast save of last undo-buffer, now with UI. */
|
||||
const bool use_memfile = (U.uiflag & USER_GLOBALUNDO) != 0;
|
||||
MemFile *memfile = use_memfile ? ED_undosys_stack_memfile_get_active(wm->undo_stack) : nullptr;
|
||||
if (memfile != nullptr) {
|
||||
if (MemFile *memfile = ED_undosys_stack_memfile_get_if_active(wm->undo_stack)) {
|
||||
/* Fast save of last undo-buffer, now with UI. */
|
||||
BLO_memfile_write_file(memfile, filepath);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
if (use_memfile) {
|
||||
/* This is very unlikely, alert developers of this unexpected case. */
|
||||
CLOG_WARN(&LOG, "undo-data not found for writing, fallback to regular file write!");
|
||||
}
|
||||
|
||||
/* Save as regular blend file with recovery information. */
|
||||
const int fileflags = (G.fileflags & ~G_FILE_COMPRESS) | G_FILE_RECOVER_WRITE;
|
||||
|
||||
ED_editors_flush_edits(bmain);
|
||||
|
||||
/* Error reporting into console. */
|
||||
BlendFileWriteParams params{};
|
||||
BLO_write_file(bmain, filepath, fileflags, ¶ms, nullptr);
|
||||
if ((U.uiflag & USER_GLOBALUNDO) == 0) {
|
||||
WM_autosave_write(wm, bmain);
|
||||
return true;
|
||||
}
|
||||
/* Can't auto-save with MemFile right now, try again later. */
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WM_autosave_is_scheduled(wmWindowManager *wm)
|
||||
{
|
||||
return wm->autosave_scheduled;
|
||||
}
|
||||
|
||||
void WM_autosave_write(wmWindowManager *wm, Main *bmain)
|
||||
{
|
||||
ED_editors_flush_edits(bmain);
|
||||
|
||||
char filepath[FILE_MAX];
|
||||
wm_autosave_location(filepath);
|
||||
/* Save as regular blend file with recovery information. */
|
||||
const int fileflags = (G.fileflags & ~G_FILE_COMPRESS) | G_FILE_RECOVER_WRITE;
|
||||
|
||||
/* Error reporting into console. */
|
||||
BlendFileWriteParams params{};
|
||||
BLO_write_file(bmain, filepath, fileflags, ¶ms, nullptr);
|
||||
|
||||
/* Restart auto-save timer. */
|
||||
wm_autosave_timer_end(wm);
|
||||
wm_autosave_timer_begin(wm);
|
||||
|
||||
wm->autosave_scheduled = false;
|
||||
}
|
||||
|
||||
static void wm_autosave_timer_begin_ex(wmWindowManager *wm, double timestep)
|
||||
@@ -2183,8 +2198,10 @@ void wm_autosave_timer(Main *bmain, wmWindowManager *wm, wmTimer * /*wt*/)
|
||||
}
|
||||
}
|
||||
|
||||
wm_autosave_write(bmain, wm);
|
||||
|
||||
wm->autosave_scheduled = false;
|
||||
if (!wm_autosave_write_try(bmain, wm)) {
|
||||
wm->autosave_scheduled = true;
|
||||
}
|
||||
/* Restart the timer after file write, just in case file write takes a long time. */
|
||||
wm_autosave_timer_begin(wm);
|
||||
}
|
||||
@@ -3410,6 +3427,7 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op)
|
||||
* often saving manually. */
|
||||
wm_autosave_timer_end(wm);
|
||||
wm_autosave_timer_begin(wm);
|
||||
wm->autosave_scheduled = false;
|
||||
}
|
||||
|
||||
if (!is_save_as && RNA_boolean_get(op->ptr, "exit")) {
|
||||
|
||||
@@ -471,29 +471,26 @@ void WM_exit_ex(bContext *C, const bool do_python_exit, const bool do_user_exit_
|
||||
/* NOTE: same code copied in `wm_files.cc`. */
|
||||
if (C && wm) {
|
||||
if (do_user_exit_actions) {
|
||||
/* save the undo state as quit.blend */
|
||||
Main *bmain = CTX_data_main(C);
|
||||
char filepath[FILE_MAX];
|
||||
BLI_path_join(filepath, sizeof(filepath), BKE_tempdir_base(), BLENDER_QUIT_FILE);
|
||||
MemFile *undo_memfile = wm->undo_stack ?
|
||||
ED_undosys_stack_memfile_get_active(wm->undo_stack) :
|
||||
ED_undosys_stack_memfile_get_if_active(wm->undo_stack) :
|
||||
nullptr;
|
||||
if (undo_memfile != nullptr) {
|
||||
/* save the undo state as quit.blend */
|
||||
Main *bmain = CTX_data_main(C);
|
||||
char filepath[FILE_MAX];
|
||||
const int fileflags = G.fileflags & ~G_FILE_COMPRESS;
|
||||
/* When true, the `undo_memfile` doesn't contain all information necessary
|
||||
* for writing and up to date blend file. */
|
||||
const bool is_memfile_outdated = ED_editors_flush_edits(bmain);
|
||||
|
||||
BLI_path_join(filepath, sizeof(filepath), BKE_tempdir_base(), BLENDER_QUIT_FILE);
|
||||
|
||||
/* When true, the `undo_memfile` doesn't contain all information necessary
|
||||
* for writing and up to date blend file. */
|
||||
const bool is_memfile_outdated = ED_editors_flush_edits(bmain);
|
||||
|
||||
BlendFileWriteParams blend_file_write_params{};
|
||||
if (is_memfile_outdated ?
|
||||
BLO_write_file(bmain, filepath, fileflags, &blend_file_write_params, nullptr) :
|
||||
BLO_memfile_write_file(undo_memfile, filepath))
|
||||
{
|
||||
printf("Saved session recovery to \"%s\"\n", filepath);
|
||||
}
|
||||
if (undo_memfile && !is_memfile_outdated) {
|
||||
BLO_memfile_write_file(undo_memfile, filepath);
|
||||
}
|
||||
else {
|
||||
const int fileflags = G.fileflags & ~G_FILE_COMPRESS;
|
||||
BlendFileWriteParams blend_file_write_params{};
|
||||
BLO_write_file(bmain, filepath, fileflags, &blend_file_write_params, nullptr);
|
||||
}
|
||||
printf("Saved session recovery to \"%s\"\n", filepath);
|
||||
}
|
||||
|
||||
WM_jobs_kill_all(wm);
|
||||
|
||||
Reference in New Issue
Block a user