For grouped undo we should not skip the undo push, rather replace the previous undo push. This way undo goes back to the state after the last operation in the group.
200 lines
7.6 KiB
C++
200 lines
7.6 KiB
C++
/*
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
*/
|
|
#ifndef __BKE_UNDO_SYSTEM_H__
|
|
#define __BKE_UNDO_SYSTEM_H__
|
|
|
|
/** \file BKE_undo_system.h
|
|
* \ingroup bke
|
|
*/
|
|
|
|
struct Main;
|
|
struct UndoStep;
|
|
struct bContext;
|
|
|
|
/* ID's */
|
|
struct Mesh;
|
|
struct Object;
|
|
struct Scene;
|
|
struct Text;
|
|
|
|
#include "DNA_ID.h"
|
|
#include "DNA_listBase.h"
|
|
|
|
typedef struct UndoRefID { struct ID *ptr; char name[MAX_ID_NAME]; } UndoRefID;
|
|
/* UndoRefID_Mesh & friends. */
|
|
#define UNDO_REF_ID_TYPE(ptr_ty) \
|
|
typedef struct UndoRefID_##ptr_ty { struct ptr_ty *ptr; char name[MAX_ID_NAME]; } UndoRefID_##ptr_ty
|
|
UNDO_REF_ID_TYPE(Mesh);
|
|
UNDO_REF_ID_TYPE(Object);
|
|
UNDO_REF_ID_TYPE(Scene);
|
|
UNDO_REF_ID_TYPE(Text);
|
|
|
|
typedef struct UndoStack {
|
|
ListBase steps;
|
|
struct UndoStep *step_active;
|
|
|
|
/**
|
|
* Some undo systems require begin/end, see: #UndoType.step_encode_init
|
|
*
|
|
* \note This is not included in the 'steps' list.
|
|
* That is done once end is called.
|
|
*/
|
|
struct UndoStep *step_init;
|
|
} UndoStack;
|
|
|
|
|
|
typedef struct UndoStep {
|
|
struct UndoStep *next, *prev;
|
|
char name[64];
|
|
const struct UndoType *type;
|
|
/** Size in bytes of all data in step (not including the step). */
|
|
size_t data_size;
|
|
/** Users should never see this step (only use for internal consistency). */
|
|
bool skip;
|
|
/* Over alloc 'type->struct_size'. */
|
|
} UndoStep;
|
|
|
|
typedef enum eUndoTypeMode {
|
|
/**
|
|
* Each undo step stores a version of the state.
|
|
* This means we can simply load in a previous state at any time.
|
|
*/
|
|
BKE_UNDOTYPE_MODE_STORE = 1,
|
|
/**
|
|
* Each undo step is a series of edits.
|
|
* This means to change states we need to apply each edit.
|
|
* It also means the 'step_decode' callback needs to detect the difference between undo and redo.
|
|
* (Currently used for text edit and image & sculpt painting).
|
|
*/
|
|
BKE_UNDOTYPE_MODE_ACCUMULATE = 2,
|
|
} eUndoTypeMode;
|
|
|
|
typedef void (*UndoTypeForEachIDRefFn)(void *user_data, struct UndoRefID *id_ref);
|
|
|
|
typedef struct UndoType {
|
|
struct UndoType *next, *prev;
|
|
/** Only for debugging. */
|
|
const char *name;
|
|
|
|
/**
|
|
* When NULL, we don't consider this undo type for context checks.
|
|
* Operators must explicitly set the undo type and handle adding the undo step.
|
|
* This is needed when tools operate on data which isn't the primary mode (eg, paint-curve in sculpt mode).
|
|
*/
|
|
bool (*poll)(struct bContext *C);
|
|
|
|
/**
|
|
* None of these callbacks manage list add/removal.
|
|
*
|
|
* Note that 'step_encode_init' is optional,
|
|
* some undo types need to perform operatons before undo push finishes.
|
|
*/
|
|
void (*step_encode_init)(struct bContext *C, UndoStep *us);
|
|
|
|
bool (*step_encode)(struct bContext *C, UndoStep *us);
|
|
void (*step_decode)(struct bContext *C, UndoStep *us, int dir);
|
|
|
|
/**
|
|
* \note When freeing all steps,
|
|
* free from the last since #MemFileUndoType will merge with the next undo type in the list. */
|
|
void (*step_free)(UndoStep *us);
|
|
|
|
void (*step_foreach_ID_ref)(UndoStep *us, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data);
|
|
|
|
eUndoTypeMode mode;
|
|
bool use_context;
|
|
|
|
int step_size;
|
|
} UndoType;
|
|
|
|
/* expose since we need to perform operations on spesific undo types (rarely). */
|
|
extern const UndoType *BKE_UNDOSYS_TYPE_IMAGE;
|
|
extern const UndoType *BKE_UNDOSYS_TYPE_MEMFILE;
|
|
extern const UndoType *BKE_UNDOSYS_TYPE_PAINTCURVE;
|
|
extern const UndoType *BKE_UNDOSYS_TYPE_PARTICLE;
|
|
extern const UndoType *BKE_UNDOSYS_TYPE_SCULPT;
|
|
extern const UndoType *BKE_UNDOSYS_TYPE_TEXT;
|
|
|
|
UndoStack *BKE_undosys_stack_create(void);
|
|
void BKE_undosys_stack_destroy(UndoStack *ustack);
|
|
void BKE_undosys_stack_clear(UndoStack *ustack);
|
|
void BKE_undosys_stack_clear_active(UndoStack *ustack);
|
|
bool BKE_undosys_stack_has_undo(UndoStack *ustack, const char *name);
|
|
void BKE_undosys_stack_init_from_main(UndoStack *ustack, struct Main *bmain);
|
|
void BKE_undosys_stack_init_from_context(UndoStack *ustack, struct bContext *C);
|
|
UndoStep *BKE_undosys_stack_active_with_type(UndoStack *ustack, const UndoType *ut);
|
|
UndoStep *BKE_undosys_stack_init_or_active_with_type(UndoStack *ustack, const UndoType *ut);
|
|
void BKE_undosys_stack_limit_steps_and_memory(UndoStack *ustack, int steps, size_t memory_limit);
|
|
|
|
/* Only some UndoType's require init. */
|
|
UndoStep *BKE_undosys_step_push_init_with_type(UndoStack *ustack, struct bContext *C, const char *name, const UndoType *ut);
|
|
UndoStep *BKE_undosys_step_push_init(UndoStack *ustack, struct bContext *C, const char *name);
|
|
|
|
bool BKE_undosys_step_push_with_type(UndoStack *ustack, struct bContext *C, const char *name, const UndoType *ut);
|
|
bool BKE_undosys_step_push(UndoStack *ustack, struct bContext *C, const char *name);
|
|
|
|
UndoStep *BKE_undosys_step_find_by_name_with_type(UndoStack *ustack, const char *name, const UndoType *ut);
|
|
UndoStep *BKE_undosys_step_find_by_type(UndoStack *ustack, const UndoType *ut);
|
|
UndoStep *BKE_undosys_step_find_by_name(UndoStack *ustack, const char *name);
|
|
|
|
bool BKE_undosys_step_undo_with_data_ex(UndoStack *ustack, struct bContext *C, UndoStep *us, bool use_skip);
|
|
bool BKE_undosys_step_undo_with_data(UndoStack *ustack, struct bContext *C, UndoStep *us);
|
|
bool BKE_undosys_step_undo(UndoStack *ustack, struct bContext *C);
|
|
|
|
bool BKE_undosys_step_redo_with_data_ex(UndoStack *ustack, struct bContext *C, UndoStep *us, bool use_skip);
|
|
bool BKE_undosys_step_redo_with_data(UndoStack *ustack, struct bContext *C, UndoStep *us);
|
|
bool BKE_undosys_step_redo(UndoStack *ustack, struct bContext *C);
|
|
|
|
bool BKE_undosys_step_load_data(UndoStack *ustack, struct bContext *C, UndoStep *us);
|
|
|
|
bool BKE_undosys_step_undo_compat_only(UndoStack *ustack, struct bContext *C, int step);
|
|
void BKE_undosys_step_undo_from_index(UndoStack *ustack, struct bContext *C, int index);
|
|
UndoStep *BKE_undosys_step_same_type_next(UndoStep *us);
|
|
UndoStep *BKE_undosys_step_same_type_prev(UndoStep *us);
|
|
|
|
/* Type System */
|
|
UndoType *BKE_undosys_type_append(void (*undosys_fn)(UndoType *));
|
|
void BKE_undosys_type_free_all(void);
|
|
|
|
/* ID Accessor */
|
|
#if 0 /* functionality is only used internally for now. */
|
|
void BKE_undosys_foreach_ID_ref(UndoStack *ustack, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data);
|
|
#endif
|
|
|
|
/* Use when the undo step stores many arbitrary pointers. */
|
|
struct UndoIDPtrMap;
|
|
struct UndoIDPtrMap *BKE_undosys_ID_map_create(void);
|
|
void BKE_undosys_ID_map_destroy(struct UndoIDPtrMap *map);
|
|
void BKE_undosys_ID_map_add(struct UndoIDPtrMap *map, ID *id);
|
|
struct ID *BKE_undosys_ID_map_lookup(const struct UndoIDPtrMap *map, const struct ID *id_src);
|
|
|
|
void BKE_undosys_ID_map_add_with_prev(
|
|
struct UndoIDPtrMap *map, struct ID *id,
|
|
struct ID **id_prev);
|
|
struct ID *BKE_undosys_ID_map_lookup_with_prev(
|
|
const struct UndoIDPtrMap *map, struct ID *id_src,
|
|
struct ID *id_prev_match[2]);
|
|
|
|
void BKE_undosys_ID_map_foreach_ID_ref(
|
|
struct UndoIDPtrMap *map,
|
|
UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data);
|
|
|
|
#endif /* __BKE_UNDO_SYSTEM_H__ */
|