fc6fc6ff3368a810acd18805985f6a02ef09a04f
[blender.git] / source / blender / blenkernel / BKE_undo_system.h
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 #ifndef __BKE_UNDO_SYSTEM_H__
17 #define __BKE_UNDO_SYSTEM_H__
18
19 /** \file
20  * \ingroup bke
21  */
22
23 struct Main;
24 struct UndoStep;
25 struct bContext;
26
27 /* ID's */
28 struct Main;
29 struct Mesh;
30 struct Object;
31 struct Scene;
32 struct Text;
33
34 #include "DNA_ID.h"
35 #include "DNA_listBase.h"
36
37 typedef struct UndoRefID {
38   struct ID *ptr;
39   char name[MAX_ID_NAME];
40 } UndoRefID;
41 /* UndoRefID_Mesh & friends. */
42 #define UNDO_REF_ID_TYPE(ptr_ty) \
43   typedef struct UndoRefID_##ptr_ty { \
44     struct ptr_ty *ptr; \
45     char name[MAX_ID_NAME]; \
46   } UndoRefID_##ptr_ty
47 UNDO_REF_ID_TYPE(Mesh);
48 UNDO_REF_ID_TYPE(Object);
49 UNDO_REF_ID_TYPE(Scene);
50 UNDO_REF_ID_TYPE(Text);
51
52 typedef struct UndoStack {
53   ListBase steps;
54   struct UndoStep *step_active;
55   /**
56    * The last memfile state read, used so we can be sure the names from the
57    * library state matches the state an undo step was written in.
58    */
59   struct UndoStep *step_active_memfile;
60
61   /**
62    * Some undo systems require begin/end, see: #UndoType.step_encode_init
63    *
64    * \note This is not included in the 'steps' list.
65    * That is done once end is called.
66    */
67   struct UndoStep *step_init;
68 } UndoStack;
69
70 typedef struct UndoStep {
71   struct UndoStep *next, *prev;
72   char name[64];
73   const struct UndoType *type;
74   /** Size in bytes of all data in step (not including the step). */
75   size_t data_size;
76   /** Users should never see this step (only use for internal consistency). */
77   bool skip;
78   /** Some situations require the global state to be stored, edge cases when exiting modes. */
79   bool use_memfile_step;
80   /** For use by undo systems that accumulate changes (text editor, painting). */
81   bool is_applied;
82   /* Over alloc 'type->struct_size'. */
83 } UndoStep;
84
85 typedef void (*UndoTypeForEachIDRefFn)(void *user_data, struct UndoRefID *id_ref);
86
87 typedef struct UndoType {
88   struct UndoType *next, *prev;
89   /** Only for debugging. */
90   const char *name;
91
92   /**
93    * When NULL, we don't consider this undo type for context checks.
94    * Operators must explicitly set the undo type and handle adding the undo step.
95    * This is needed when tools operate on data which isn't the primary mode (eg, paint-curve in sculpt mode).
96    */
97   bool (*poll)(struct bContext *C);
98
99   /**
100    * None of these callbacks manage list add/removal.
101    *
102    * Note that 'step_encode_init' is optional,
103    * some undo types need to perform operatons before undo push finishes.
104    */
105   void (*step_encode_init)(struct bContext *C, UndoStep *us);
106
107   bool (*step_encode)(struct bContext *C, struct Main *bmain, UndoStep *us);
108   void (*step_decode)(struct bContext *C, struct Main *bmain, UndoStep *us, int dir);
109
110   /**
111    * \note When freeing all steps,
112    * free from the last since #MemFileUndoType will merge with the next undo type in the list. */
113   void (*step_free)(UndoStep *us);
114
115   void (*step_foreach_ID_ref)(UndoStep *us,
116                               UndoTypeForEachIDRefFn foreach_ID_ref_fn,
117                               void *user_data);
118
119   bool use_context;
120
121   int step_size;
122 } UndoType;
123
124 /* expose since we need to perform operations on spesific undo types (rarely). */
125 extern const UndoType *BKE_UNDOSYS_TYPE_IMAGE;
126 extern const UndoType *BKE_UNDOSYS_TYPE_MEMFILE;
127 extern const UndoType *BKE_UNDOSYS_TYPE_PAINTCURVE;
128 extern const UndoType *BKE_UNDOSYS_TYPE_PARTICLE;
129 extern const UndoType *BKE_UNDOSYS_TYPE_SCULPT;
130 extern const UndoType *BKE_UNDOSYS_TYPE_TEXT;
131
132 #define BKE_UNDOSYS_TYPE_IS_MEMFILE_SKIP(ty) ELEM(ty, BKE_UNDOSYS_TYPE_IMAGE)
133
134 UndoStack *BKE_undosys_stack_create(void);
135 void BKE_undosys_stack_destroy(UndoStack *ustack);
136 void BKE_undosys_stack_clear(UndoStack *ustack);
137 void BKE_undosys_stack_clear_active(UndoStack *ustack);
138 bool BKE_undosys_stack_has_undo(UndoStack *ustack, const char *name);
139 void BKE_undosys_stack_init_from_main(UndoStack *ustack, struct Main *bmain);
140 void BKE_undosys_stack_init_from_context(UndoStack *ustack, struct bContext *C);
141 UndoStep *BKE_undosys_stack_active_with_type(UndoStack *ustack, const UndoType *ut);
142 UndoStep *BKE_undosys_stack_init_or_active_with_type(UndoStack *ustack, const UndoType *ut);
143 void BKE_undosys_stack_limit_steps_and_memory(UndoStack *ustack, int steps, size_t memory_limit);
144
145 /* Only some UndoType's require init. */
146 UndoStep *BKE_undosys_step_push_init_with_type(UndoStack *ustack,
147                                                struct bContext *C,
148                                                const char *name,
149                                                const UndoType *ut);
150 UndoStep *BKE_undosys_step_push_init(UndoStack *ustack, struct bContext *C, const char *name);
151
152 bool BKE_undosys_step_push_with_type(UndoStack *ustack,
153                                      struct bContext *C,
154                                      const char *name,
155                                      const UndoType *ut);
156 bool BKE_undosys_step_push(UndoStack *ustack, struct bContext *C, const char *name);
157
158 UndoStep *BKE_undosys_step_find_by_name_with_type(UndoStack *ustack,
159                                                   const char *name,
160                                                   const UndoType *ut);
161 UndoStep *BKE_undosys_step_find_by_type(UndoStack *ustack, const UndoType *ut);
162 UndoStep *BKE_undosys_step_find_by_name(UndoStack *ustack, const char *name);
163
164 bool BKE_undosys_step_undo_with_data_ex(UndoStack *ustack,
165                                         struct bContext *C,
166                                         UndoStep *us,
167                                         bool use_skip);
168 bool BKE_undosys_step_undo_with_data(UndoStack *ustack, struct bContext *C, UndoStep *us);
169 bool BKE_undosys_step_undo(UndoStack *ustack, struct bContext *C);
170
171 bool BKE_undosys_step_redo_with_data_ex(UndoStack *ustack,
172                                         struct bContext *C,
173                                         UndoStep *us,
174                                         bool use_skip);
175 bool BKE_undosys_step_redo_with_data(UndoStack *ustack, struct bContext *C, UndoStep *us);
176 bool BKE_undosys_step_redo(UndoStack *ustack, struct bContext *C);
177
178 bool BKE_undosys_step_load_data(UndoStack *ustack, struct bContext *C, UndoStep *us);
179
180 void BKE_undosys_step_undo_from_index(UndoStack *ustack, struct bContext *C, int index);
181 UndoStep *BKE_undosys_step_same_type_next(UndoStep *us);
182 UndoStep *BKE_undosys_step_same_type_prev(UndoStep *us);
183
184 /* Type System */
185 UndoType *BKE_undosys_type_append(void (*undosys_fn)(UndoType *));
186 void BKE_undosys_type_free_all(void);
187
188 /* ID Accessor */
189 #if 0 /* functionality is only used internally for now. */
190 void BKE_undosys_foreach_ID_ref(UndoStack *ustack,
191                                 UndoTypeForEachIDRefFn foreach_ID_ref_fn,
192                                 void *user_data);
193 #endif
194
195 /* Use when the undo step stores many arbitrary pointers. */
196 struct UndoIDPtrMap;
197 struct UndoIDPtrMap *BKE_undosys_ID_map_create(void);
198 void BKE_undosys_ID_map_destroy(struct UndoIDPtrMap *map);
199 void BKE_undosys_ID_map_add(struct UndoIDPtrMap *map, ID *id);
200 struct ID *BKE_undosys_ID_map_lookup(const struct UndoIDPtrMap *map, const struct ID *id_src);
201
202 void BKE_undosys_ID_map_add_with_prev(struct UndoIDPtrMap *map,
203                                       struct ID *id,
204                                       struct ID **id_prev);
205 struct ID *BKE_undosys_ID_map_lookup_with_prev(const struct UndoIDPtrMap *map,
206                                                struct ID *id_src,
207                                                struct ID *id_prev_match[2]);
208
209 void BKE_undosys_ID_map_foreach_ID_ref(struct UndoIDPtrMap *map,
210                                        UndoTypeForEachIDRefFn foreach_ID_ref_fn,
211                                        void *user_data);
212
213 void BKE_undosys_print(UndoStack *ustack);
214
215 #endif /* __BKE_UNDO_SYSTEM_H__ */