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

blender_undo.c « intern « blenkernel « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: f22dfc6054a13e2ce3367f36c081725e2d26e0e9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/* SPDX-License-Identifier: GPL-2.0-or-later */

/** \file
 * \ingroup bke
 *
 * 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

#include <errno.h>
#include <fcntl.h> /* for open */
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#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"

#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->filepath, &params, &bf_reports);
    if (bfd != NULL) {
      BKE_blendfile_read_setup(C, bfd, &params, &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, &params, NULL);
    if (bfd != NULL) {
      BKE_blendfile_read_setup(C, bfd, &params, &(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 filepath[FILE_MAX];
    char numstr[32];

    /* Calculate current filepath. */
    counter++;
    counter = counter % U.undosteps;

    BLI_snprintf(numstr, sizeof(numstr), "%d.blend", counter);
    BLI_path_join(filepath, sizeof(filepath), BKE_tempdir_session(), numstr);

    /* success = */ /* UNUSED */ BLO_write_file(
        bmain, filepath, fileflags, &(const struct BlendFileWriteParams){0}, NULL);

    BLI_strncpy(mfu->filepath, filepath, sizeof(mfu->filepath));
  }
  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);
}

/** \} */