1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 #pragma once
17 
18 /** \file
19  * \ingroup bke
20  */
21 
22 #include "DNA_ID.h"
23 #include "DNA_listBase.h"
24 
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28 
29 struct Main;
30 struct UndoStep;
31 struct bContext;
32 
33 /* ID's */
34 struct Main;
35 struct Mesh;
36 struct Object;
37 struct Scene;
38 struct Text;
39 
40 typedef struct UndoRefID {
41   struct ID *ptr;
42   char name[MAX_ID_NAME];
43 } UndoRefID;
44 /* UndoRefID_Mesh & friends. */
45 #define UNDO_REF_ID_TYPE(ptr_ty) \
46   typedef struct UndoRefID_##ptr_ty { \
47     struct ptr_ty *ptr; \
48     char name[MAX_ID_NAME]; \
49   } UndoRefID_##ptr_ty
50 UNDO_REF_ID_TYPE(Mesh);
51 UNDO_REF_ID_TYPE(Object);
52 UNDO_REF_ID_TYPE(Scene);
53 UNDO_REF_ID_TYPE(Text);
54 UNDO_REF_ID_TYPE(Image);
55 UNDO_REF_ID_TYPE(PaintCurve);
56 
57 typedef struct UndoStack {
58   ListBase steps;
59   struct UndoStep *step_active;
60   /**
61    * The last memfile state read, used so we can be sure the names from the
62    * library state matches the state an undo step was written in.
63    */
64   struct UndoStep *step_active_memfile;
65 
66   /**
67    * Some undo systems require begin/end, see: #UndoType.step_encode_init
68    *
69    * \note This is not included in the 'steps' list.
70    * That is done once end is called.
71    */
72   struct UndoStep *step_init;
73 
74   /**
75    * Keep track of nested group begin/end calls,
76    * within which all but the last undo-step is marked for skipping.
77    */
78   int group_level;
79 } UndoStack;
80 
81 typedef struct UndoStep {
82   struct UndoStep *next, *prev;
83   char name[64];
84   const struct UndoType *type;
85   /** Size in bytes of all data in step (not including the step). */
86   size_t data_size;
87   /** Users should never see this step (only use for internal consistency). */
88   bool skip;
89   /** Some situations require the global state to be stored, edge cases when exiting modes. */
90   bool use_memfile_step;
91   /** When this is true, undo/memfile read code is allowed to re-use old data-blocks for unchanged
92    * IDs, and existing depsgraphes. This has to be forbidden in some cases (like renamed IDs). */
93   bool use_old_bmain_data;
94   /** For use by undo systems that accumulate changes (text editor, painting). */
95   bool is_applied;
96   /* Over alloc 'type->struct_size'. */
97 } UndoStep;
98 
99 typedef void (*UndoTypeForEachIDRefFn)(void *user_data, struct UndoRefID *id_ref);
100 
101 typedef struct UndoType {
102   struct UndoType *next, *prev;
103   /** Only for debugging. */
104   const char *name;
105 
106   /**
107    * When NULL, we don't consider this undo type for context checks.
108    * Operators must explicitly set the undo type and handle adding the undo step.
109    * This is needed when tools operate on data which isn't the primary mode
110    * (eg, paint-curve in sculpt mode).
111    */
112   bool (*poll)(struct bContext *C);
113 
114   /**
115    * None of these callbacks manage list add/removal.
116    *
117    * Note that 'step_encode_init' is optional,
118    * some undo types need to perform operations before undo push finishes.
119    */
120   void (*step_encode_init)(struct bContext *C, UndoStep *us);
121 
122   bool (*step_encode)(struct bContext *C, struct Main *bmain, UndoStep *us);
123   void (*step_decode)(
124       struct bContext *C, struct Main *bmain, UndoStep *us, int dir, bool is_final);
125 
126   /**
127    * \note When freeing all steps,
128    * free from the last since #BKE_UNDOSYS_TYPE_MEMFILE
129    * will merge with the next undo type in the list.
130    */
131   void (*step_free)(UndoStep *us);
132 
133   void (*step_foreach_ID_ref)(UndoStep *us,
134                               UndoTypeForEachIDRefFn foreach_ID_ref_fn,
135                               void *user_data);
136 
137   bool use_context;
138 
139   int step_size;
140 } UndoType;
141 
142 /* Expose since we need to perform operations on specific undo types (rarely). */
143 extern const UndoType *BKE_UNDOSYS_TYPE_IMAGE;
144 extern const UndoType *BKE_UNDOSYS_TYPE_MEMFILE;
145 extern const UndoType *BKE_UNDOSYS_TYPE_PAINTCURVE;
146 extern const UndoType *BKE_UNDOSYS_TYPE_PARTICLE;
147 extern const UndoType *BKE_UNDOSYS_TYPE_SCULPT;
148 extern const UndoType *BKE_UNDOSYS_TYPE_TEXT;
149 
150 #define BKE_UNDOSYS_TYPE_IS_MEMFILE_SKIP(ty) ELEM(ty, BKE_UNDOSYS_TYPE_IMAGE)
151 
152 UndoStack *BKE_undosys_stack_create(void);
153 void BKE_undosys_stack_destroy(UndoStack *ustack);
154 void BKE_undosys_stack_clear(UndoStack *ustack);
155 void BKE_undosys_stack_clear_active(UndoStack *ustack);
156 bool BKE_undosys_stack_has_undo(UndoStack *ustack, const char *name);
157 void BKE_undosys_stack_init_from_main(UndoStack *ustack, struct Main *bmain);
158 void BKE_undosys_stack_init_from_context(UndoStack *ustack, struct bContext *C);
159 UndoStep *BKE_undosys_stack_active_with_type(UndoStack *ustack, const UndoType *ut);
160 UndoStep *BKE_undosys_stack_init_or_active_with_type(UndoStack *ustack, const UndoType *ut);
161 void BKE_undosys_stack_limit_steps_and_memory(UndoStack *ustack, int steps, size_t memory_limit);
162 #define BKE_undosys_stack_limit_steps_and_memory_defaults(ustack) \
163   BKE_undosys_stack_limit_steps_and_memory(ustack, U.undosteps, (size_t)U.undomemory * 1024 * 1024)
164 
165 void BKE_undosys_stack_group_begin(UndoStack *ustack);
166 void BKE_undosys_stack_group_end(UndoStack *ustack);
167 
168 /* Only some UndoType's require init. */
169 UndoStep *BKE_undosys_step_push_init_with_type(UndoStack *ustack,
170                                                struct bContext *C,
171                                                const char *name,
172                                                const UndoType *ut);
173 UndoStep *BKE_undosys_step_push_init(UndoStack *ustack, struct bContext *C, const char *name);
174 
175 bool BKE_undosys_step_push_with_type(UndoStack *ustack,
176                                      struct bContext *C,
177                                      const char *name,
178                                      const UndoType *ut);
179 bool BKE_undosys_step_push(UndoStack *ustack, struct bContext *C, const char *name);
180 
181 UndoStep *BKE_undosys_step_find_by_name_with_type(UndoStack *ustack,
182                                                   const char *name,
183                                                   const UndoType *ut);
184 UndoStep *BKE_undosys_step_find_by_type(UndoStack *ustack, const UndoType *ut);
185 UndoStep *BKE_undosys_step_find_by_name(UndoStack *ustack, const char *name);
186 
187 bool BKE_undosys_step_undo_with_data_ex(UndoStack *ustack,
188                                         struct bContext *C,
189                                         UndoStep *us,
190                                         bool use_skip);
191 bool BKE_undosys_step_undo_with_data(UndoStack *ustack, struct bContext *C, UndoStep *us);
192 bool BKE_undosys_step_undo(UndoStack *ustack, struct bContext *C);
193 
194 bool BKE_undosys_step_redo_with_data_ex(UndoStack *ustack,
195                                         struct bContext *C,
196                                         UndoStep *us,
197                                         bool use_skip);
198 bool BKE_undosys_step_redo_with_data(UndoStack *ustack, struct bContext *C, UndoStep *us);
199 bool BKE_undosys_step_redo(UndoStack *ustack, struct bContext *C);
200 
201 bool BKE_undosys_step_load_data(UndoStack *ustack, struct bContext *C, UndoStep *us);
202 
203 void BKE_undosys_step_undo_from_index(UndoStack *ustack, struct bContext *C, int index);
204 UndoStep *BKE_undosys_step_same_type_next(UndoStep *us);
205 UndoStep *BKE_undosys_step_same_type_prev(UndoStep *us);
206 
207 /* Type System */
208 UndoType *BKE_undosys_type_append(void (*undosys_fn)(UndoType *));
209 void BKE_undosys_type_free_all(void);
210 
211 /* ID Accessor */
212 #if 0 /* functionality is only used internally for now. */
213 void BKE_undosys_foreach_ID_ref(UndoStack *ustack,
214                                 UndoTypeForEachIDRefFn foreach_ID_ref_fn,
215                                 void *user_data);
216 #endif
217 
218 void BKE_undosys_print(UndoStack *ustack);
219 
220 #ifdef __cplusplus
221 }
222 #endif
223