Cleanup: Subdiv: Remove common_ prefix
[blender.git] / source / blender / blenkernel / BKE_undo_system.hh
blobbb6b4afc0305eb3a784411f23850be40e2602ecc
1 /* SPDX-FileCopyrightText: 2023 Blender Authors
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4 #pragma once
6 /** \file
7 * \ingroup bke
8 */
10 #include "BLI_path_utils.hh"
11 #include "BLI_utildefines.h"
12 #include "DNA_ID.h"
13 #include "DNA_listBase.h"
15 struct Main;
16 struct UndoStep;
17 struct UndoType;
18 struct bContext;
20 /* IDs */
21 struct GreasePencil;
22 struct Main;
23 struct Mesh;
24 struct Object;
25 struct Scene;
26 struct Text;
28 struct UndoRefID {
29 struct ID *ptr;
30 char name[MAX_ID_NAME];
31 char library_filepath_abs[FILE_MAX];
33 /* UndoRefID_Mesh & friends. */
34 #define UNDO_REF_ID_TYPE(ptr_ty) \
35 struct UndoRefID_##ptr_ty { \
36 struct ptr_ty *ptr; \
37 char name[MAX_ID_NAME]; \
38 char library_filepath_abs[FILE_MAX]; \
40 UNDO_REF_ID_TYPE(GreasePencil);
41 UNDO_REF_ID_TYPE(Mesh);
42 UNDO_REF_ID_TYPE(Object);
43 UNDO_REF_ID_TYPE(Scene);
44 UNDO_REF_ID_TYPE(Text);
45 UNDO_REF_ID_TYPE(Image);
46 UNDO_REF_ID_TYPE(PaintCurve);
48 struct UndoStack {
49 ListBase steps;
50 UndoStep *step_active;
51 /**
52 * The last memfile state read, used so we can be sure the names from the
53 * library state matches the state an undo step was written in.
55 UndoStep *step_active_memfile;
57 /**
58 * Some undo systems require begin/end, see: #UndoType.step_encode_init
60 * \note This is not included in the 'steps' list.
61 * That is done once end is called.
63 UndoStep *step_init;
65 /**
66 * Keep track of nested group begin/end calls,
67 * within which all but the last undo-step is marked for skipping.
69 int group_level;
72 struct UndoStep {
73 UndoStep *next, *prev;
74 char name[64];
75 const UndoType *type;
76 /** Size in bytes of all data in step (not including the step). */
77 size_t data_size;
78 /** Users should never see this step (only use for internal consistency). */
79 bool skip;
80 /** Some situations require the global state to be stored, edge cases when exiting modes. */
81 bool use_memfile_step;
82 /** When this is true, undo/memfile read code is allowed to re-use old data-blocks for unchanged
83 * IDs, and existing depsgraphs. This has to be forbidden in some cases (like renamed IDs). */
84 bool use_old_bmain_data;
85 /** For use by undo systems that accumulate changes (mesh-sculpt & image-painting). */
86 bool is_applied;
87 /* Over alloc 'type->struct_size'. */
90 enum eUndoStepDir {
91 STEP_REDO = 1,
92 STEP_UNDO = -1,
93 STEP_INVALID = 0,
96 enum eUndoPushReturn {
97 UNDO_PUSH_RET_FAILURE = 0,
98 UNDO_PUSH_RET_SUCCESS = (1 << 0),
99 UNDO_PUSH_RET_OVERRIDE_CHANGED = (1 << 1),
101 ENUM_OPERATORS(eUndoPushReturn, UNDO_PUSH_RET_OVERRIDE_CHANGED)
103 using UndoTypeForEachIDRefFn = void (*)(void *user_data, UndoRefID *id_ref);
105 struct UndoType {
106 UndoType *next, *prev;
107 /** Only for debugging. */
108 const char *name;
111 * When NULL, we don't consider this undo type for context checks.
112 * Operators must explicitly set the undo type and handle adding the undo step.
113 * This is needed when tools operate on data which isn't the primary mode
114 * (eg, paint-curve in sculpt mode).
116 bool (*poll)(struct bContext *C);
119 * None of these callbacks manage list add/removal.
121 * Note that 'step_encode_init' is optional,
122 * some undo types need to perform operations before undo push finishes.
124 void (*step_encode_init)(bContext *C, UndoStep *us);
126 bool (*step_encode)(bContext *C, Main *bmain, UndoStep *us);
127 void (*step_decode)(bContext *C, Main *bmain, UndoStep *us, eUndoStepDir dir, bool is_final);
130 * \note When freeing all steps,
131 * free from the last since #BKE_UNDOSYS_TYPE_MEMFILE
132 * will merge with the next undo type in the list.
134 void (*step_free)(UndoStep *us);
136 void (*step_foreach_ID_ref)(UndoStep *us,
137 UndoTypeForEachIDRefFn foreach_ID_ref_fn,
138 void *user_data);
140 /** Information for the generic undo system to refine handling of this specific undo type. */
141 uint flags;
144 * The size of the undo struct 'inherited' from #UndoStep for that specific type. Used for
145 * generic allocation in BKE's `undo_system.cc`. */
146 size_t step_size;
149 /** #UndoType.flag bit-flags. */
150 enum eUndoTypeFlags {
152 * This undo type `encode` callback needs a valid context, it will fail otherwise.
153 * \note Callback is still supposed to properly deal with a NULL context pointer.
155 UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE = 1 << 0,
158 * When the active undo step is of this type, it must be read before loading other undo steps.
160 * This is typically used for undo systems that store both before/after states.
162 UNDOTYPE_FLAG_DECODE_ACTIVE_STEP = 1 << 1,
165 /* -------------------------------------------------------------------- */
166 /** \name Public Undo Types
168 * Expose since we need to perform operations on specific undo types (rarely).
169 * \{ */
171 extern const UndoType *BKE_UNDOSYS_TYPE_IMAGE;
172 extern const UndoType *BKE_UNDOSYS_TYPE_MEMFILE;
173 extern const UndoType *BKE_UNDOSYS_TYPE_PAINTCURVE;
174 extern const UndoType *BKE_UNDOSYS_TYPE_PARTICLE;
175 extern const UndoType *BKE_UNDOSYS_TYPE_SCULPT;
176 extern const UndoType *BKE_UNDOSYS_TYPE_TEXT;
178 /** \} */
180 #define BKE_UNDOSYS_TYPE_IS_MEMFILE_SKIP(ty) ELEM(ty, BKE_UNDOSYS_TYPE_IMAGE)
182 UndoStack *BKE_undosys_stack_create();
183 void BKE_undosys_stack_destroy(UndoStack *ustack);
184 void BKE_undosys_stack_clear(UndoStack *ustack);
185 void BKE_undosys_stack_clear_active(UndoStack *ustack);
186 /* name optional */
187 bool BKE_undosys_stack_has_undo(const UndoStack *ustack, const char *name);
188 void BKE_undosys_stack_init_from_main(UndoStack *ustack, Main *bmain);
189 /* called after 'BKE_undosys_stack_init_from_main' */
190 void BKE_undosys_stack_init_from_context(UndoStack *ustack, bContext *C);
191 UndoStep *BKE_undosys_stack_active_with_type(UndoStack *ustack, const UndoType *ut);
192 UndoStep *BKE_undosys_stack_init_or_active_with_type(UndoStack *ustack, const UndoType *ut);
194 * \param steps: Limit the number of undo steps.
195 * \param memory_limit: Limit the amount of memory used by the undo stack.
197 void BKE_undosys_stack_limit_steps_and_memory(UndoStack *ustack, int steps, size_t memory_limit);
198 #define BKE_undosys_stack_limit_steps_and_memory_defaults(ustack) \
199 BKE_undosys_stack_limit_steps_and_memory(ustack, U.undosteps, (size_t)U.undomemory * 1024 * 1024)
201 void BKE_undosys_stack_group_begin(UndoStack *ustack);
202 void BKE_undosys_stack_group_end(UndoStack *ustack);
205 * Only some UndoType's require init.
207 UndoStep *BKE_undosys_step_push_init_with_type(UndoStack *ustack,
208 bContext *C,
209 const char *name,
210 const UndoType *ut);
211 UndoStep *BKE_undosys_step_push_init(UndoStack *ustack, bContext *C, const char *name);
214 * \param C: Can be NULL from some callers if their encoding function doesn't need it
216 eUndoPushReturn BKE_undosys_step_push_with_type(UndoStack *ustack,
217 bContext *C,
218 const char *name,
219 const UndoType *ut);
220 eUndoPushReturn BKE_undosys_step_push(UndoStack *ustack, bContext *C, const char *name);
222 UndoStep *BKE_undosys_step_find_by_name_with_type(UndoStack *ustack,
223 const char *name,
224 const UndoType *ut);
225 UndoStep *BKE_undosys_step_find_by_type(UndoStack *ustack, const UndoType *ut);
226 UndoStep *BKE_undosys_step_find_by_name(UndoStack *ustack, const char *name);
229 * Return direction of the undo/redo from `us_reference` (or `ustack->step_active` if NULL), and
230 * `us_target`.
232 * \note If `us_reference` and `us_target` are the same, we consider this is an undo.
234 * \return -1 for undo, 1 for redo, 0 in case of error.
236 eUndoStepDir BKE_undosys_step_calc_direction(const UndoStack *ustack,
237 const UndoStep *us_target,
238 const UndoStep *us_reference);
241 * Undo/Redo until the given `us_target` step becomes the active (currently loaded) one.
243 * \note Unless `us_target` is a 'skipped' one and `use_skip` is true, `us_target`
244 * will become the active step.
246 * \note In case `use_skip` is true, the final target will always be **beyond** the given one
247 * (if the given one has to be skipped).
249 * \param us_reference: If NULL, will be set to current active step in the undo stack. Otherwise,
250 * it is assumed to match the current state, and will be used as basis for the undo/redo process
251 * (i.e. all steps in-between `us_reference` and `us_target` will be processed).
253 bool BKE_undosys_step_load_data_ex(
254 UndoStack *ustack, bContext *C, UndoStep *us_target, UndoStep *us_reference, bool use_skip);
256 * Undo/Redo until the given `us_target` step becomes the active (currently loaded) one.
258 bool BKE_undosys_step_load_data(UndoStack *ustack, bContext *C, UndoStep *us_target);
260 * Undo/Redo until the step matching given `index` in the undo stack becomes the active
261 * (currently loaded) one.
263 void BKE_undosys_step_load_from_index(UndoStack *ustack, bContext *C, int index);
266 * Undo until `us_target` step becomes the active (currently loaded) one.
268 * \warning This function assumes that the given target step is _before_ current active one.
270 * \note Unless `us_target` is a 'skipped' one and `use_skip` is true,
271 * `us_target` will become the active step.
273 * \note In case `use_skip` is true, the final target will always be **before** the given one
274 * (if the given one has to be skipped).
276 bool BKE_undosys_step_undo_with_data_ex(UndoStack *ustack,
277 bContext *C,
278 UndoStep *us_target,
279 bool use_skip);
281 * Undo until `us_target` step becomes the active (currently loaded) one.
283 * \note See #BKE_undosys_step_undo_with_data_ex for details.
285 bool BKE_undosys_step_undo_with_data(UndoStack *ustack, bContext *C, UndoStep *us_target);
287 * Undo one step from current active (currently loaded) one.
289 bool BKE_undosys_step_undo(UndoStack *ustack, bContext *C);
292 * Redo until `us_target` step becomes the active (currently loaded) one.
294 * \warning This function assumes that the given target step is _after_ current active one.
296 * \note Unless `us_target` is a 'skipped' one and `use_skip` is true,
297 * `us_target` will become the active step.
299 * \note In case `use_skip` is true, the final target will always be **after** the given one
300 * (if the given one has to be skipped).
302 bool BKE_undosys_step_redo_with_data_ex(UndoStack *ustack,
303 bContext *C,
304 UndoStep *us_target,
305 bool use_skip);
307 * Redo until `us_target` step becomes the active (currently loaded) one.
309 * \note See #BKE_undosys_step_redo_with_data_ex for details.
311 bool BKE_undosys_step_redo_with_data(UndoStack *ustack, bContext *C, UndoStep *us_target);
313 * Redo one step from current active one.
315 bool BKE_undosys_step_redo(UndoStack *ustack, bContext *C);
318 * Useful when we want to diff against previous undo data but can't be sure the types match.
320 UndoStep *BKE_undosys_step_same_type_next(UndoStep *us);
322 * Useful when we want to diff against previous undo data but can't be sure the types match.
324 UndoStep *BKE_undosys_step_same_type_prev(UndoStep *us);
326 /* Type System. */
329 * Similar to #WM_operatortype_append
331 UndoType *BKE_undosys_type_append(void (*undosys_fn)(UndoType *));
332 void BKE_undosys_type_free_all();
334 /* ID Accessor. */
336 #if 0 /* functionality is only used internally for now. */
337 void BKE_undosys_foreach_ID_ref(UndoStack *ustack,
338 UndoTypeForEachIDRefFn foreach_ID_ref_fn,
339 void *user_data);
340 #endif
342 void BKE_undosys_print(UndoStack *ustack);