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