2022-02-11 09:07:11 +11:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
2016-04-24 22:42:41 +10:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup bke
|
2016-04-24 22:42:41 +10:00
|
|
|
*
|
|
|
|
|
* Blend file undo (known as 'Global Undo').
|
|
|
|
|
* DNA level diffing for undo.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifndef _WIN32
|
|
|
|
|
# include <unistd.h> /* for read close */
|
|
|
|
|
#else
|
|
|
|
|
# include <io.h> /* for open close read */
|
|
|
|
|
#endif
|
|
|
|
|
|
2020-03-19 09:33:03 +01:00
|
|
|
#include <errno.h>
|
|
|
|
|
#include <fcntl.h> /* for open */
|
2016-04-24 22:42:41 +10:00
|
|
|
#include <stddef.h>
|
2020-03-19 09:33:03 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
2016-04-24 22:42:41 +10:00
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
|
|
#include "DNA_scene_types.h"
|
|
|
|
|
|
|
|
|
|
#include "BLI_path_util.h"
|
|
|
|
|
#include "BLI_string.h"
|
|
|
|
|
#include "BLI_utildefines.h"
|
|
|
|
|
|
2018-11-07 15:37:31 +01:00
|
|
|
#include "BKE_appdir.h"
|
2016-04-24 22:42:41 +10:00
|
|
|
#include "BKE_blender_undo.h" /* own include */
|
|
|
|
|
#include "BKE_blendfile.h"
|
|
|
|
|
#include "BKE_context.h"
|
|
|
|
|
#include "BKE_global.h"
|
|
|
|
|
#include "BKE_main.h"
|
2021-02-04 22:03:39 +01:00
|
|
|
#include "BKE_undo_system.h"
|
2016-04-24 22:42:41 +10:00
|
|
|
|
2018-11-22 14:57:41 +11:00
|
|
|
#include "BLO_readfile.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BLO_undofile.h"
|
2016-04-24 22:42:41 +10:00
|
|
|
#include "BLO_writefile.h"
|
|
|
|
|
|
2017-04-06 16:11:50 +02:00
|
|
|
#include "DEG_depsgraph.h"
|
|
|
|
|
|
2016-04-24 22:42:41 +10:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Global Undo
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
#define UNDO_DISK 0
|
|
|
|
|
|
2020-03-17 12:29:36 +01:00
|
|
|
bool BKE_memfile_undo_decode(MemFileUndoData *mfu,
|
2021-02-04 22:03:39 +01:00
|
|
|
const eUndoStepDir undo_direction,
|
2020-03-17 12:29:36 +01:00
|
|
|
const bool use_old_bmain_data,
|
|
|
|
|
bContext *C)
|
2016-04-24 22:42:41 +10:00
|
|
|
{
|
2018-06-05 15:10:33 +02:00
|
|
|
Main *bmain = CTX_data_main(C);
|
2021-12-13 16:22:19 +11:00
|
|
|
char mainstr[sizeof(bmain->filepath)];
|
2016-04-24 22:42:41 +10:00
|
|
|
int success = 0, fileflags;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-06-05 15:10:33 +02:00
|
|
|
BLI_strncpy(mainstr, BKE_main_blendfile_path(bmain), sizeof(mainstr)); /* temporal store */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-04-24 22:42:41 +10:00
|
|
|
fileflags = G.fileflags;
|
|
|
|
|
G.fileflags |= G_FILE_NO_UI;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-03-27 14:44:17 +02:00
|
|
|
if (UNDO_DISK) {
|
2021-03-12 00:34:21 +11:00
|
|
|
const struct BlendFileReadParams params = {0};
|
2021-06-24 10:53:45 +02:00
|
|
|
BlendFileReadReport bf_reports = {.reports = NULL};
|
2022-05-17 11:38:05 +10:00
|
|
|
struct BlendFileData *bfd = BKE_blendfile_read(mfu->filepath, ¶ms, &bf_reports);
|
2021-03-12 00:34:21 +11:00
|
|
|
if (bfd != NULL) {
|
2021-06-24 10:53:45 +02:00
|
|
|
BKE_blendfile_read_setup(C, bfd, ¶ms, &bf_reports);
|
2021-03-12 00:34:21 +11:00
|
|
|
success = true;
|
|
|
|
|
}
|
2018-03-27 14:44:17 +02:00
|
|
|
}
|
|
|
|
|
else {
|
2020-03-17 12:29:36 +01:00
|
|
|
struct BlendFileReadParams params = {0};
|
2021-02-04 22:03:39 +01:00
|
|
|
params.undo_direction = undo_direction;
|
2020-03-17 12:29:36 +01:00
|
|
|
if (!use_old_bmain_data) {
|
|
|
|
|
params.skip_flags |= BLO_READ_SKIP_UNDO_OLD_MAIN;
|
|
|
|
|
}
|
2021-03-12 00:34:21 +11:00
|
|
|
struct BlendFileData *bfd = BKE_blendfile_read_from_memfile(
|
|
|
|
|
bmain, &mfu->memfile, ¶ms, NULL);
|
|
|
|
|
if (bfd != NULL) {
|
2021-06-23 09:51:11 +02:00
|
|
|
BKE_blendfile_read_setup(C, bfd, ¶ms, &(BlendFileReadReport){NULL});
|
2021-03-12 00:34:21 +11:00
|
|
|
success = true;
|
|
|
|
|
}
|
2018-03-27 14:44:17 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-06-06 09:36:50 +02:00
|
|
|
/* Restore, bmain has been re-allocated. */
|
|
|
|
|
bmain = CTX_data_main(C);
|
2021-12-13 16:22:19 +11:00
|
|
|
STRNCPY(bmain->filepath, mainstr);
|
2016-04-24 22:42:41 +10:00
|
|
|
G.fileflags = fileflags;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-04-24 22:42:41 +10:00
|
|
|
if (success) {
|
2018-09-24 18:46:51 +02:00
|
|
|
/* important not to update time here, else non keyed transforms are lost */
|
2021-06-21 14:05:13 +02:00
|
|
|
DEG_tag_on_visible_update(bmain, false);
|
2016-04-24 22:42:41 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-04-24 22:42:41 +10:00
|
|
|
return success;
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-19 14:17:59 +01:00
|
|
|
MemFileUndoData *BKE_memfile_undo_encode(Main *bmain, MemFileUndoData *mfu_prev)
|
2016-04-24 22:42:41 +10:00
|
|
|
{
|
2018-03-19 14:17:59 +01:00
|
|
|
MemFileUndoData *mfu = MEM_callocN(sizeof(MemFileUndoData), __func__);
|
2016-04-24 22:42:41 +10:00
|
|
|
|
2021-03-21 13:18:20 +11:00
|
|
|
/* Include recovery information since undo-data is written out as #BLENDER_QUIT_FILE. */
|
2021-03-15 13:30:43 +11:00
|
|
|
const int fileflags = G.fileflags | G_FILE_RECOVER_WRITE;
|
|
|
|
|
|
2016-04-24 22:42:41 +10:00
|
|
|
/* disk save version */
|
|
|
|
|
if (UNDO_DISK) {
|
|
|
|
|
static int counter = 0;
|
2022-05-17 11:38:05 +10:00
|
|
|
char filepath[FILE_MAX];
|
2016-04-24 22:42:41 +10:00
|
|
|
char numstr[32];
|
|
|
|
|
|
2022-05-17 11:38:05 +10:00
|
|
|
/* Calculate current filepath. */
|
2016-04-24 22:42:41 +10:00
|
|
|
counter++;
|
|
|
|
|
counter = counter % U.undosteps;
|
|
|
|
|
|
|
|
|
|
BLI_snprintf(numstr, sizeof(numstr), "%d.blend", counter);
|
2022-05-17 11:38:05 +10:00
|
|
|
BLI_join_dirfile(filepath, sizeof(filepath), BKE_tempdir_session(), numstr);
|
2016-04-24 22:42:41 +10:00
|
|
|
|
2020-06-19 15:41:07 +10:00
|
|
|
/* success = */ /* UNUSED */ BLO_write_file(
|
2022-05-17 11:38:05 +10:00
|
|
|
bmain, filepath, fileflags, &(const struct BlendFileWriteParams){0}, NULL);
|
2016-04-24 22:42:41 +10:00
|
|
|
|
2022-05-17 11:38:05 +10:00
|
|
|
BLI_strncpy(mfu->filepath, filepath, sizeof(mfu->filepath));
|
2016-04-24 22:42:41 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2018-03-19 14:17:59 +01:00
|
|
|
MemFile *prevfile = (mfu_prev) ? &(mfu_prev->memfile) : NULL;
|
2020-03-28 21:48:07 +01:00
|
|
|
if (prevfile) {
|
|
|
|
|
BLO_memfile_clear_future(prevfile);
|
|
|
|
|
}
|
2021-03-15 13:30:43 +11:00
|
|
|
/* success = */ /* UNUSED */ BLO_write_file_mem(bmain, prevfile, &mfu->memfile, fileflags);
|
2018-03-19 14:17:59 +01:00
|
|
|
mfu->undo_size = mfu->memfile.size;
|
2016-04-24 22:42:41 +10:00
|
|
|
}
|
|
|
|
|
|
2018-03-19 14:17:59 +01:00
|
|
|
bmain->is_memfile_undo_written = true;
|
2016-04-24 22:42:41 +10:00
|
|
|
|
2018-03-19 14:17:59 +01:00
|
|
|
return mfu;
|
2016-04-24 22:42:41 +10:00
|
|
|
}
|
|
|
|
|
|
2018-03-19 14:17:59 +01:00
|
|
|
void BKE_memfile_undo_free(MemFileUndoData *mfu)
|
Implement grouped undo option for operators
This option makes an operator to not push a task to the undo stack if the previous stored elemen is the same operator or part of the same undo group.
The main usage is for animation, so you can change frames to inspect the
poses, and revert the previous pose without having to roll back tons of
"change frame" operator, or even see the undo stack full.
This complements rB13ee9b8e
Design with help by Sergey Sharybin.
Reviewers: sergey, mont29
Reviewed By: mont29, sergey
Subscribers: pyc0d3r, hjalti, Severin, lowercase, brecht, monio, aligorith, hadrien, jbakker
Differential Revision: https://developer.blender.org/D2330
2016-11-15 11:50:11 +01:00
|
|
|
{
|
2018-03-19 14:17:59 +01:00
|
|
|
BLO_memfile_free(&mfu->memfile);
|
|
|
|
|
MEM_freeN(mfu);
|
2016-04-24 22:42:41 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \} */
|