/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /** \file * \ingroup bke * * Blend file undo (known as 'Global Undo'). * DNA level diffing for undo. */ #ifndef _WIN32 # include /* for read close */ #else # include /* for open close read */ #endif #include #include /* for open */ #include #include #include #include #include "MEM_guardedalloc.h" #include "DNA_scene_types.h" #include "BLI_path_util.h" #include "BLI_string.h" #include "BLI_utildefines.h" #include "BKE_appdir.h" #include "BKE_blender_undo.h" /* own include */ #include "BKE_blendfile.h" #include "BKE_context.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_undo_system.h" #include "BLO_readfile.h" #include "BLO_undofile.h" #include "BLO_writefile.h" #include "DEG_depsgraph.h" /* -------------------------------------------------------------------- */ /** \name Global Undo * \{ */ #define UNDO_DISK 0 bool BKE_memfile_undo_decode(MemFileUndoData *mfu, const eUndoStepDir undo_direction, const bool use_old_bmain_data, bContext *C) { Main *bmain = CTX_data_main(C); char mainstr[sizeof(bmain->filepath)]; int success = 0, fileflags; BLI_strncpy(mainstr, BKE_main_blendfile_path(bmain), sizeof(mainstr)); /* temporal store */ fileflags = G.fileflags; G.fileflags |= G_FILE_NO_UI; if (UNDO_DISK) { const struct BlendFileReadParams params = {0}; BlendFileReadReport bf_reports = {.reports = NULL}; struct BlendFileData *bfd = BKE_blendfile_read(mfu->filename, ¶ms, &bf_reports); if (bfd != NULL) { BKE_blendfile_read_setup(C, bfd, ¶ms, &bf_reports); success = true; } } else { struct BlendFileReadParams params = {0}; params.undo_direction = undo_direction; if (!use_old_bmain_data) { params.skip_flags |= BLO_READ_SKIP_UNDO_OLD_MAIN; } struct BlendFileData *bfd = BKE_blendfile_read_from_memfile( bmain, &mfu->memfile, ¶ms, NULL); if (bfd != NULL) { BKE_blendfile_read_setup(C, bfd, ¶ms, &(BlendFileReadReport){NULL}); success = true; } } /* Restore, bmain has been re-allocated. */ bmain = CTX_data_main(C); STRNCPY(bmain->filepath, mainstr); G.fileflags = fileflags; if (success) { /* important not to update time here, else non keyed transforms are lost */ DEG_tag_on_visible_update(bmain, false); } return success; } MemFileUndoData *BKE_memfile_undo_encode(Main *bmain, MemFileUndoData *mfu_prev) { MemFileUndoData *mfu = MEM_callocN(sizeof(MemFileUndoData), __func__); /* Include recovery information since undo-data is written out as #BLENDER_QUIT_FILE. */ const int fileflags = G.fileflags | G_FILE_RECOVER_WRITE; /* disk save version */ if (UNDO_DISK) { static int counter = 0; char filename[FILE_MAX]; char numstr[32]; /* Calculate current filename. */ counter++; counter = counter % U.undosteps; 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, &(const struct BlendFileWriteParams){0}, NULL); BLI_strncpy(mfu->filename, filename, sizeof(mfu->filename)); } else { MemFile *prevfile = (mfu_prev) ? &(mfu_prev->memfile) : NULL; if (prevfile) { BLO_memfile_clear_future(prevfile); } /* success = */ /* UNUSED */ BLO_write_file_mem(bmain, prevfile, &mfu->memfile, fileflags); mfu->undo_size = mfu->memfile.size; } bmain->is_memfile_undo_written = true; return mfu; } void BKE_memfile_undo_free(MemFileUndoData *mfu) { BLO_memfile_free(&mfu->memfile); MEM_freeN(mfu); } /** \} */