[Bf-blender-cvs] [651b8fb14eb] master: Undo: unified undo system w/ linear history

Campbell Barton noreply at git.blender.org
Sat Mar 31 20:41:04 CEST 2018


Commit: 651b8fb14eb6ee5cbfa98bffe80a966a0753b14e
Author: Campbell Barton
Date:   Mon Mar 19 14:17:59 2018 +0100
Branches: master
https://developer.blender.org/rB651b8fb14eb6ee5cbfa98bffe80a966a0753b14e

Undo: unified undo system w/ linear history

- Use a single undo history for all operations.
- UndoType's are registered and poll the context to check if they
  should be used when performing an undo push.
- Mode switching is used to ensure the state is correct before
  undo data is restored.
- Some undo types accumulate changes (image & text editing)
  others store the state multiple times (with de-duplication).
  This is supported by checking UndoStack.mode `ACCUMULATE` / `STORE`.
- Each undo step stores ID datablocks they use with utilities to help
  manage restoring correct ID's.
  Needed since global undo is now mixed with other modes undo.
- Currently performs each undo step when going up/down history
  Previously this wasn't done, making history fail in some cases.
  This can be optimized to skip some combinations of undo steps.

grease-pencil is an exception which has not been updated
since it integrates undo into the draw-session.

See D3113

===================================================================

M	build_files/cmake/macros.cmake
M	source/blender/blenkernel/BKE_blender_undo.h
M	source/blender/blenkernel/BKE_main.h
M	source/blender/blenkernel/BKE_pointcache.h
A	source/blender/blenkernel/BKE_undo_system.h
M	source/blender/blenkernel/CMakeLists.txt
M	source/blender/blenkernel/intern/blender_undo.c
M	source/blender/blenkernel/intern/library.c
A	source/blender/blenkernel/intern/undo_system.c
M	source/blender/blenloader/BLO_readfile.h
M	source/blender/blenloader/BLO_undofile.h
M	source/blender/blenloader/intern/readfile.c
M	source/blender/blenloader/intern/undofile.c
M	source/blender/editors/armature/editarmature_undo.c
M	source/blender/editors/curve/editcurve.c
M	source/blender/editors/curve/editcurve_undo.c
M	source/blender/editors/curve/editfont_undo.c
M	source/blender/editors/include/ED_armature.h
M	source/blender/editors/include/ED_curve.h
M	source/blender/editors/include/ED_lattice.h
M	source/blender/editors/include/ED_mball.h
M	source/blender/editors/include/ED_mesh.h
M	source/blender/editors/include/ED_object.h
M	source/blender/editors/include/ED_paint.h
M	source/blender/editors/include/ED_particle.h
M	source/blender/editors/include/ED_sculpt.h
M	source/blender/editors/include/ED_text.h
M	source/blender/editors/include/ED_util.h
M	source/blender/editors/lattice/editlattice_undo.c
M	source/blender/editors/mesh/editmesh_undo.c
M	source/blender/editors/metaball/editmball_undo.c
M	source/blender/editors/object/object_edit.c
M	source/blender/editors/object/object_modes.c
M	source/blender/editors/physics/particle_edit.c
M	source/blender/editors/physics/particle_edit_undo.c
M	source/blender/editors/physics/particle_object.c
M	source/blender/editors/physics/physics_intern.h
M	source/blender/editors/render/render_internal.c
M	source/blender/editors/sculpt_paint/CMakeLists.txt
M	source/blender/editors/sculpt_paint/paint_curve.c
M	source/blender/editors/sculpt_paint/paint_curve_undo.c
M	source/blender/editors/sculpt_paint/paint_image.c
M	source/blender/editors/sculpt_paint/paint_image_2d.c
M	source/blender/editors/sculpt_paint/paint_image_proj.c
M	source/blender/editors/sculpt_paint/paint_image_undo.c
M	source/blender/editors/sculpt_paint/paint_intern.h
D	source/blender/editors/sculpt_paint/paint_undo.c
M	source/blender/editors/sculpt_paint/sculpt_intern.h
M	source/blender/editors/sculpt_paint/sculpt_undo.c
M	source/blender/editors/space_image/image_ops.c
M	source/blender/editors/space_text/CMakeLists.txt
M	source/blender/editors/space_text/text_ops.c
A	source/blender/editors/space_text/text_undo.c
M	source/blender/editors/util/CMakeLists.txt
M	source/blender/editors/util/ed_util.c
D	source/blender/editors/util/editmode_undo.c
A	source/blender/editors/util/memfile_undo.c
M	source/blender/editors/util/undo.c
A	source/blender/editors/util/undo_system_types.c
M	source/blender/editors/util/util_intern.h
M	source/blender/makesdna/DNA_windowmanager_types.h
A	source/blender/windowmanager/WM_undo.h
M	source/blender/windowmanager/intern/wm.c
M	source/blender/windowmanager/intern/wm_files.c
M	source/blender/windowmanager/intern/wm_init_exit.c
M	source/creator/creator_signals.c

===================================================================

diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake
index f0cff75c417..3f0868229e2 100644
--- a/build_files/cmake/macros.cmake
+++ b/build_files/cmake/macros.cmake
@@ -559,6 +559,9 @@ function(SETUP_BLENDER_SORTED_LIBS)
 	set(BLENDER_SORTED_LIBS
 		bf_windowmanager
 
+		# needed twice because of text undo
+		bf_editor_util
+
 		bf_editor_space_api
 		bf_editor_space_action
 		bf_editor_space_buttons
diff --git a/source/blender/blenkernel/BKE_blender_undo.h b/source/blender/blenkernel/BKE_blender_undo.h
index 84a6d07be7d..a96f8af1fdb 100644
--- a/source/blender/blenkernel/BKE_blender_undo.h
+++ b/source/blender/blenkernel/BKE_blender_undo.h
@@ -31,22 +31,13 @@ extern "C" {
 struct bContext;
 struct Scene;
 struct Main;
+struct MemFileUndoData;
 
 #define BKE_UNDO_STR_MAX 64
 
-/* global undo */
-extern void          BKE_undo_write(struct bContext *C, const char *name);
-extern void          BKE_undo_step(struct bContext *C, int step);
-extern void          BKE_undo_name(struct bContext *C, const char *name);
-extern bool          BKE_undo_is_valid(const char *name);
-extern void          BKE_undo_reset(void);
-extern void          BKE_undo_number(struct bContext *C, int nr);
-extern const char   *BKE_undo_get_name(int nr, bool *r_active);
-extern const char   *BKE_undo_get_name_last(void);
-extern bool          BKE_undo_save_file(const char *filename);
-extern struct Main  *BKE_undo_get_main(struct Scene **r_scene);
-
-extern void          BKE_undo_callback_wm_kill_jobs_set(void (*callback)(struct bContext *C));
+struct MemFileUndoData *BKE_memfile_undo_encode(struct Main *bmain, struct MemFileUndoData *mfu_prev);
+bool                    BKE_memfile_undo_decode(struct MemFileUndoData *mfu, struct bContext *C);
+void                    BKE_memfile_undo_free(struct MemFileUndoData *mfu);
 
 #ifdef __cplusplus
 }
diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
index d8318bfcf5d..e224155726f 100644
--- a/source/blender/blenkernel/BKE_main.h
+++ b/source/blender/blenkernel/BKE_main.h
@@ -84,10 +84,12 @@ typedef struct Main {
 	short minversionfile, minsubversionfile;
 	uint64_t build_commit_timestamp; /* commit's timestamp from buildinfo */
 	char build_hash[16];  /* hash from buildinfo */
-	short recovered;	/* indicate the main->name (file) is the recovered one */
+	char recovered;	/* indicate the main->name (file) is the recovered one */
+	/** All current ID's exist in the last memfile undo step. */
+	char is_memfile_undo_written;
 
 	BlendThumbnail *blen_thumb;
-	
+
 	struct Library *curlib;
 	ListBase scene;
 	ListBase library;
diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h
index f31ae715539..cc60df1b2d6 100644
--- a/source/blender/blenkernel/BKE_pointcache.h
+++ b/source/blender/blenkernel/BKE_pointcache.h
@@ -227,7 +227,6 @@ typedef struct PTCacheEditPoint {
 } PTCacheEditPoint;
 
 typedef struct PTCacheUndo {
-	struct PTCacheUndo *next, *prev;
 	struct PTCacheEditPoint *points;
 
 	/* particles stuff */
@@ -240,12 +239,11 @@ typedef struct PTCacheUndo {
 	struct ListBase mem_cache;
 
 	int totpoint;
-	char name[64];
+
+	size_t undo_size;
 } PTCacheUndo;
 
 typedef struct PTCacheEdit {
-	ListBase undo;
-	struct PTCacheUndo *curundo;
 	PTCacheEditPoint *points;
 
 	struct PTCacheID pid;
diff --git a/source/blender/blenkernel/BKE_undo_system.h b/source/blender/blenkernel/BKE_undo_system.h
new file mode 100644
index 00000000000..6072ecfae4a
--- /dev/null
+++ b/source/blender/blenkernel/BKE_undo_system.h
@@ -0,0 +1,187 @@
+/*
+ * ***** 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_MEMFILE;
+extern const UndoType *BKE_UNDOSYS_TYPE_IMAGE;
+extern const UndoType *BKE_UNDOSYS_TYPE_SCULPT;
+extern const UndoType *BKE_UNDOSYS_TYPE_PARTICLE;
+extern const UndoType *BKE_UNDOSYS_TYPE_PAINTCURVE;
+
+UndoStack      *BKE_undosys_stack_create(void);
+void            BKE_undosys_stack_destroy(UndoStack *ustack);
+void            BKE_undosys_stack_clear(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);
+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. */
+void BKE_undosys_step_push_init_with_type(UndoStack *ustack, struct bContext *C, const char *name, const UndoType *ut);
+void 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_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 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list