Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2018-04-01 12:03:25 +0300
committerCampbell Barton <ideasman42@gmail.com>2018-04-01 12:03:25 +0300
commitb65ea517eb932bde950bde51979c6a3fd258efa8 (patch)
tree8f3a291a7e1778bb3af45cdb1d98a621efbd1a7d /source/blender/editors/util
parent916c91bd08933d596eaca3e369467daf7964612e (diff)
parent473f17b3d557adbb06b89e0a186be48a0129086d (diff)
Merge branch 'master' into blender2.8
- Undo that changes modes currently asserts, since undo is now screen data. Most likely we will change how object mode and workspaces work since it's not practical/maintainable at the moment. - Removed view_layer from particle settings (wasn't needed and complicated undo).
Diffstat (limited to 'source/blender/editors/util')
-rw-r--r--source/blender/editors/util/CMakeLists.txt4
-rw-r--r--source/blender/editors/util/ed_util.c18
-rw-r--r--source/blender/editors/util/editmode_undo.c373
-rw-r--r--source/blender/editors/util/memfile_undo.c149
-rw-r--r--source/blender/editors/util/undo.c327
-rw-r--r--source/blender/editors/util/undo_system_types.c74
-rw-r--r--source/blender/editors/util/util_intern.h14
7 files changed, 310 insertions, 649 deletions
diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt
index 71a3322cb50..bd9077a2fca 100644
--- a/source/blender/editors/util/CMakeLists.txt
+++ b/source/blender/editors/util/CMakeLists.txt
@@ -31,6 +31,7 @@ set(INC
../../makesrna
../../windowmanager
../../../../intern/guardedalloc
+ ../../../../intern/clog
../../../../intern/glew-mx
)
@@ -41,9 +42,10 @@ set(INC_SYS
set(SRC
ed_transverts.c
ed_util.c
- editmode_undo.c
+ memfile_undo.c
numinput.c
undo.c
+ undo_system_types.c
util_intern.h
# general includes
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index 7a5b8bfbda1..4bec0d9f114 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -62,6 +62,7 @@
#include "BKE_screen.h"
#include "BKE_workspace.h"
#include "BKE_layer.h"
+#include "BKE_undo_system.h"
#include "ED_armature.h"
#include "ED_buttons.h"
@@ -93,13 +94,16 @@ void ED_editors_init(bContext *C)
{
wmWindowManager *wm = CTX_wm_manager(C);
+ if (wm->undo_stack == NULL) {
+ wm->undo_stack = BKE_undosys_stack_create();
+ }
+
/* This is called during initialization, so we don't want to store any reports */
ReportList *reports = CTX_wm_reports(C);
int reports_flag_prev = reports->flag & ~RPT_STORE;
SWAP(int, reports->flag, reports_flag_prev);
-
/* toggle on modes for objects that were saved with these enabled. for
* e.g. linked objects we have to ensure that they are actually the
* active object in this scene. */
@@ -150,10 +154,16 @@ void ED_editors_exit(bContext *C)
if (!bmain)
return;
-
+
/* frees all editmode undos */
- undo_editmode_clear();
- ED_undo_paint_free();
+ if (G.main->wm.first) {
+ wmWindowManager *wm = G.main->wm.first;
+ /* normally we don't check for NULL undo stack, do here since it may run in different context. */
+ if (wm->undo_stack) {
+ BKE_undosys_stack_destroy(wm->undo_stack);
+ wm->undo_stack = NULL;
+ }
+ }
for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
if (ob->type == OB_MESH) {
diff --git a/source/blender/editors/util/editmode_undo.c b/source/blender/editors/util/editmode_undo.c
deleted file mode 100644
index 43d1bfe1e6c..00000000000
--- a/source/blender/editors/util/editmode_undo.c
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * ***** 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.
- *
- * The Original Code is Copyright (C) 2004 Blender Foundation
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/editors/util/editmode_undo.c
- * \ingroup edutil
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_object_types.h"
-
-#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
-
-#include "BKE_blender_undo.h"
-#include "BKE_context.h"
-#include "BKE_global.h"
-
-#include "DEG_depsgraph.h"
-
-#include "ED_util.h"
-#include "ED_mesh.h"
-
-#include "util_intern.h"
-
-/* ****** XXX ***** */
-static void error(const char *UNUSED(arg)) {}
-/* ****** XXX ***** */
-
-typedef struct UndoElem {
- struct UndoElem *next, *prev;
- /** copy of edit-mode object ID */
- ID id;
- /** pointer to edited object */
- Object *ob;
- /** type of edited object */
- int type;
- void *undodata;
- uintptr_t undosize;
- char name[BKE_UNDO_STR_MAX];
-
- /** Use context to retrieve current edit-data. */
- void * (*getdata)(bContext * C);
- /** Pointer to function freeing data. */
- void (*freedata)(void *);
- /** Data to edit-mode conversion. */
- void (*to_editmode)(void *, void *, void *);
- /** Edit-mode to data conversion. */
- void * (*from_editmode)(void *, void *);
- /** Check if undo data is still valid. */
- int (*validate_undo)(void *, void *);
-} UndoElem;
-
-static ListBase g_undobase = {NULL, NULL};
-static UndoElem *g_curundo = NULL;
-
-static void undo_restore(UndoElem *undo, void *editdata, void *obdata)
-{
- if (undo) {
- undo->to_editmode(undo->undodata, editdata, obdata);
- }
-}
-
-/**
- * name can be a dynamic string
- * See #UndoElem for callbacks docs.
- * */
-void undo_editmode_push(
- bContext *C, const char *name,
- void * (*getdata)(bContext * C),
- void (*freedata)(void *),
- void (*to_editmode)(void *, void *, void *),
- void *(*from_editmode)(void *, void *),
- int (*validate_undo)(void *, void *))
-{
- UndoElem *uel;
- Object *obedit = CTX_data_edit_object(C);
- void *editdata;
- int nr;
- uintptr_t mem_used, mem_total, mem_max;
-
- /* at first here was code to prevent an "original" key to be inserted twice
- * this was giving conflicts for example when mesh changed due to keys or apply */
-
- /* remove all undos after (also when g_curundo == NULL) */
- while (g_undobase.last != g_curundo) {
- uel = g_undobase.last;
- uel->freedata(uel->undodata);
- BLI_freelinkN(&g_undobase, uel);
- }
-
- /* make new */
- g_curundo = uel = MEM_callocN(sizeof(UndoElem), "undo editmode");
- BLI_strncpy(uel->name, name, sizeof(uel->name));
- BLI_addtail(&g_undobase, uel);
-
- uel->getdata = getdata;
- uel->freedata = freedata;
- uel->to_editmode = to_editmode;
- uel->from_editmode = from_editmode;
- uel->validate_undo = validate_undo;
-
- /* limit amount to the maximum amount*/
- nr = 0;
- uel = g_undobase.last;
- while (uel) {
- nr++;
- if (nr == U.undosteps) {
- break;
- }
- uel = uel->prev;
- }
- if (uel) {
- while (g_undobase.first != uel) {
- UndoElem *first = g_undobase.first;
- first->freedata(first->undodata);
- BLI_freelinkN(&g_undobase, first);
- }
- }
-
- /* copy */
- mem_used = MEM_get_memory_in_use();
- editdata = getdata(C);
- g_curundo->undodata = g_curundo->from_editmode(editdata, obedit->data);
- g_curundo->undosize = MEM_get_memory_in_use() - mem_used;
- g_curundo->ob = obedit;
- g_curundo->id = obedit->id;
- g_curundo->type = obedit->type;
-
- if (U.undomemory != 0) {
- /* limit to maximum memory (afterwards, we can't know in advance) */
- mem_total = 0;
- mem_max = ((uintptr_t)U.undomemory) * 1024 * 1024;
-
- uel = g_undobase.last;
- while (uel && uel->prev) {
- mem_total += uel->undosize;
- if (mem_total > mem_max) {
- break;
- }
- uel = uel->prev;
- }
-
- if (uel) {
- if (uel->prev && uel->prev->prev) {
- uel = uel->prev;
- }
- while (g_undobase.first != uel) {
- UndoElem *first = g_undobase.first;
- first->freedata(first->undodata);
- BLI_freelinkN(&g_undobase, first);
- }
- }
- }
-}
-
-/* helper to remove clean other objects from undo stack */
-static void undo_clean_stack(bContext *C)
-{
- UndoElem *uel;
- Object *obedit = CTX_data_edit_object(C);
-
- /* global undo changes pointers, so we also allow identical names */
- /* side effect: when deleting/renaming object and start editing new one with same name */
-
- uel = g_undobase.first;
- while (uel) {
- void *editdata = uel->getdata(C);
- bool is_valid = false;
- UndoElem *uel_next = uel->next;
-
- /* for when objects are converted, renamed, or global undo changes pointers... */
- if (uel->type == obedit->type) {
- if (STREQ(uel->id.name, obedit->id.name)) {
- if (uel->validate_undo == NULL) {
- is_valid = true;
- }
- else if (uel->validate_undo(uel->undodata, editdata)) {
- is_valid = true;
- }
- }
- }
- if (is_valid) {
- uel->ob = obedit;
- }
- else {
- if (uel == g_curundo) {
- g_curundo = NULL;
- }
-
- uel->freedata(uel->undodata);
- BLI_freelinkN(&g_undobase, uel);
- }
-
- uel = uel_next;
- }
-
- if (g_curundo == NULL) {
- g_curundo = g_undobase.last;
- }
-}
-
-/**
- * 1 = an undo, -1 is a redo.
- * we have to make sure 'g_curundo' remains at current situation
- */
-void undo_editmode_step(bContext *C, int step)
-{
- Object *obedit = CTX_data_edit_object(C);
-
- /* prevent undo to happen on wrong object, stack can be a mix */
- undo_clean_stack(C);
-
- if (step == 0) {
- undo_restore(g_curundo, g_curundo->getdata(C), obedit->data);
- }
- else if (step == 1) {
- if (g_curundo == NULL || g_curundo->prev == NULL) {
- error("No more steps to undo");
- }
- else {
- if (G.debug & G_DEBUG) printf("undo %s\n", g_curundo->name);
- g_curundo = g_curundo->prev;
- undo_restore(g_curundo, g_curundo->getdata(C), obedit->data);
- }
- }
- else {
- /* g_curundo has to remain current situation! */
- if (g_curundo == NULL || g_curundo->next == NULL) {
- error("No more steps to redo");
- }
- else {
- undo_restore(g_curundo->next, g_curundo->getdata(C), obedit->data);
- g_curundo = g_curundo->next;
- if (G.debug & G_DEBUG) printf("redo %s\n", g_curundo->name);
- }
- }
-
- /* special case for editmesh, mode must be copied back to the scene */
- if (obedit->type == OB_MESH) {
- EDBM_selectmode_to_scene(C);
- }
-
- DEG_id_tag_update(&obedit->id, OB_RECALC_DATA);
-
- /* XXX notifiers */
-}
-
-void undo_editmode_clear(void)
-{
- UndoElem *uel;
-
- uel = g_undobase.first;
- while (uel) {
- uel->freedata(uel->undodata);
- uel = uel->next;
- }
- BLI_freelistN(&g_undobase);
- g_curundo = NULL;
-}
-
-/* based on index nr it does a restore */
-void undo_editmode_number(bContext *C, int nr)
-{
- UndoElem *uel;
- int a = 1;
-
- for (uel = g_undobase.first; uel; uel = uel->next, a++) {
- if (a == nr) {
- break;
- }
- }
- g_curundo = uel;
- undo_editmode_step(C, 0);
-}
-
-void undo_editmode_name(bContext *C, const char *undoname)
-{
- UndoElem *uel;
-
- for (uel = g_undobase.last; uel; uel = uel->prev) {
- if (STREQ(undoname, uel->name)) {
- break;
- }
- }
- if (uel && uel->prev) {
- g_curundo = uel->prev;
- undo_editmode_step(C, 0);
- }
-}
-
-/**
- * \a undoname is optional, when NULL it just checks for existing undo steps
- */
-bool undo_editmode_is_valid(const char *undoname)
-{
- if (undoname) {
- UndoElem *uel;
-
- for (uel = g_undobase.last; uel; uel = uel->prev) {
- if (STREQ(undoname, uel->name)) {
- break;
- }
- }
- return uel != NULL;
- }
- return g_undobase.last != g_undobase.first;
-}
-
-
-/**
- * Get name of undo item, return null if no item with this index.
- *
- * if active pointer, set it to 1 if true
- */
-const char *undo_editmode_get_name(bContext *C, int nr, bool *r_active)
-{
- UndoElem *uel;
-
- /* prevent wrong numbers to be returned */
- undo_clean_stack(C);
-
- if (r_active) {
- *r_active = false;
- }
-
- uel = BLI_findlink(&g_undobase, nr);
- if (uel) {
- if (r_active && (uel == g_curundo)) {
- *r_active = true;
- }
- return uel->name;
- }
- return NULL;
-}
-
-
-void *undo_editmode_get_prev(Object *ob)
-{
- UndoElem *ue = g_undobase.last;
- if (ue && ue->prev && ue->prev->ob == ob) {
- return ue->prev->undodata;
- }
- return NULL;
-}
diff --git a/source/blender/editors/util/memfile_undo.c b/source/blender/editors/util/memfile_undo.c
new file mode 100644
index 00000000000..95af0c48147
--- /dev/null
+++ b/source/blender/editors/util/memfile_undo.c
@@ -0,0 +1,149 @@
+/*
+ * ***** 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 *****
+ */
+
+/** \file blender/editors/util/memfile_undo.c
+ * \ingroup edutil
+ *
+ * Wrapper between 'BKE_undo.h' and 'BKE_undo_system.h'
+ */
+
+#include "BLI_utildefines.h"
+#include "BLI_sys_types.h"
+
+#include "DNA_object_enums.h"
+
+#include "BKE_blender_undo.h"
+#include "BKE_context.h"
+#include "BKE_undo_system.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_object.h"
+#include "ED_util.h"
+#include "ED_render.h"
+
+
+#include "../blenloader/BLO_undofile.h"
+
+#include "util_intern.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Implements ED Undo System
+ * \{ */
+
+typedef struct MemFileUndoStep {
+ UndoStep step;
+ MemFileUndoData *data;
+} MemFileUndoStep;
+
+static bool memfile_undosys_poll(bContext *UNUSED(C))
+{
+ /* other poll functions must run first, this is a catch-all. */
+
+ if ((U.uiflag & USER_GLOBALUNDO) == 0) {
+ return false;
+ }
+ return true;
+}
+
+static bool memfile_undosys_step_encode(struct bContext *C, UndoStep *us_p)
+{
+ MemFileUndoStep *us = (MemFileUndoStep *)us_p;
+
+ /* Important we only use 'main' from the context (see: BKE_undosys_stack_init_from_main). */
+ struct Main *bmain = CTX_data_main(C);
+
+ /* can be NULL, use when set. */
+ MemFileUndoStep *us_prev = (MemFileUndoStep *)BKE_undosys_step_same_type_prev(us_p);
+ us->data = BKE_memfile_undo_encode(bmain, us_prev ? us_prev->data : NULL);
+ us->step.data_size = us->data->undo_size;
+ return true;
+}
+
+static void memfile_undosys_step_decode(struct bContext *C, UndoStep *us_p, int UNUSED(dir))
+{
+ /* Loading the content will correctly switch into compatible non-object modes. */
+ ED_object_mode_set(C, OB_MODE_OBJECT);
+
+ /* This is needed so undoing/redoing doesn't crash with threaded previews going */
+ ED_viewport_render_kill_jobs(CTX_wm_manager(C), CTX_data_main(C), true);
+ MemFileUndoStep *us = (MemFileUndoStep *)us_p;
+ BKE_memfile_undo_decode(us->data, C);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, CTX_data_scene(C));
+}
+
+static void memfile_undosys_step_free(UndoStep *us_p)
+{
+ /* To avoid unnecessary slow down, free backwards (so we don't need to merge when clearing all). */
+ MemFileUndoStep *us = (MemFileUndoStep *)us_p;
+ if (us_p->next != NULL) {
+ UndoStep *us_next_p = BKE_undosys_step_same_type_next(us_p);
+ if (us_next_p != NULL) {
+ MemFileUndoStep *us_next = (MemFileUndoStep *)us_next_p;
+ BLO_memfile_merge(&us->data->memfile, &us_next->data->memfile);
+ }
+ }
+
+ BKE_memfile_undo_free(us->data);
+}
+
+/* Export for ED_undo_sys. */
+void ED_memfile_undosys_type(UndoType *ut)
+{
+ ut->name = "Global Undo";
+ ut->poll = memfile_undosys_poll;
+ ut->step_encode = memfile_undosys_step_encode;
+ ut->step_decode = memfile_undosys_step_decode;
+ ut->step_free = memfile_undosys_step_free;
+
+ ut->mode = BKE_UNDOTYPE_MODE_STORE;
+ ut->use_context = true;
+
+ ut->step_size = sizeof(MemFileUndoStep);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Utilities
+ * \{ */
+
+/**
+ * Ideally we wouldn't need to export global undo internals, there are some cases where it's needed though.
+ */
+static struct MemFile *ed_undosys_step_get_memfile(UndoStep *us_p)
+{
+ MemFileUndoStep *us = (MemFileUndoStep *)us_p;
+ return &us->data->memfile;
+}
+
+struct MemFile *ED_undosys_stack_memfile_get_active(UndoStack *ustack)
+{
+ UndoStep *us = BKE_undosys_stack_active_with_type(ustack, BKE_UNDOSYS_TYPE_MEMFILE);
+ if (us) {
+ return ed_undosys_step_get_memfile(us);
+ }
+ return NULL;
+}
+
+
+/** \} */
diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c
index b7101e7ae99..99e90eb73e8 100644
--- a/source/blender/editors/util/undo.c
+++ b/source/blender/editors/util/undo.c
@@ -48,6 +48,7 @@
#include "BKE_library_override.h"
#include "BKE_main.h"
#include "BKE_screen.h"
+#include "BKE_undo_system.h"
#include "DEG_depsgraph.h"
@@ -80,42 +81,27 @@
void ED_undo_push(bContext *C, const char *str)
{
- const WorkSpace *workspace = CTX_wm_workspace(C);
- Object *obedit = CTX_data_edit_object(C);
- Object *obact = CTX_data_active_object(C);
-
- if (G.debug & G_DEBUG)
+ if (G.debug & G_DEBUG) {
printf("%s: %s\n", __func__, str);
-
- /* Always do it for now, this might need to be refined... */
- BKE_main_override_static_operations_create(CTX_data_main(C));
-
- if (obedit) {
- if (U.undosteps == 0) return;
-
- if (obedit->type == OB_MESH)
- undo_push_mesh(C, str);
- else if (ELEM(obedit->type, OB_CURVE, OB_SURF))
- undo_push_curve(C, str);
- else if (obedit->type == OB_FONT)
- undo_push_font(C, str);
- else if (obedit->type == OB_MBALL)
- undo_push_mball(C, str);
- else if (obedit->type == OB_LATTICE)
- undo_push_lattice(C, str);
- else if (obedit->type == OB_ARMATURE)
- undo_push_armature(C, str);
}
- else if (obact && workspace->object_mode & OB_MODE_PARTICLE_EDIT) {
- if (U.undosteps == 0) return;
+ const int steps = U.undosteps;
- PE_undo_push(CTX_data_scene(C), CTX_data_view_layer(C), str);
+ if (steps <= 0) {
+ return;
}
- else if (obact && workspace->object_mode & OB_MODE_SCULPT) {
- /* do nothing for now */
+
+ wmWindowManager *wm = CTX_wm_manager(C);
+
+ /* Only apply limit if this is the last undo step. */
+ if (wm->undo_stack->step_active && (wm->undo_stack->step_active->next == NULL)) {
+ BKE_undosys_stack_limit_steps_and_memory(wm->undo_stack, steps - 1, 0);
}
- else {
- BKE_undo_write(C, str);
+
+ BKE_undosys_step_push(wm->undo_stack, C, str);
+
+ if (U.undomemory != 0) {
+ const size_t memory_limit = (size_t)U.undomemory * 1024 * 1024;
+ BKE_undosys_stack_limit_steps_and_memory(wm->undo_stack, 0, memory_limit);
}
WM_file_tag_modified();
@@ -124,15 +110,10 @@ void ED_undo_push(bContext *C, const char *str)
/* note: also check undo_history_exec() in bottom if you change notifiers */
static int ed_undo_step(bContext *C, int step, const char *undoname)
{
- const WorkSpace *workspace = CTX_wm_workspace(C);
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
- Main *bmain = CTX_data_main(C);
+ // Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *obedit = CTX_data_edit_object(C);
- Object *obact = CTX_data_active_object(C);
- ScrArea *sa = CTX_wm_area(C);
/* undo during jobs are running can easily lead to freeing data using by jobs,
* or they can just lead to freezing job in some other cases */
@@ -140,100 +121,45 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
return OPERATOR_CANCELLED;
}
+ /* TODO(campbell): undo_system: use undo system */
/* grease pencil can be can be used in plenty of spaces, so check it first */
if (ED_gpencil_session_active()) {
return ED_undo_gpencil_step(C, step, undoname);
}
- if (sa && (sa->spacetype == SPACE_IMAGE)) {
- SpaceImage *sima = (SpaceImage *)sa->spacedata.first;
-
- if ((obact && (workspace->object_mode & OB_MODE_TEXTURE_PAINT)) || (sima->mode == SI_MODE_PAINT)) {
- if (!ED_undo_paint_step(C, UNDO_PAINT_IMAGE, step, undoname) && undoname) {
- if (U.uiflag & USER_GLOBALUNDO) {
- ED_viewport_render_kill_jobs(wm, bmain, true);
- BKE_undo_name(C, undoname);
- }
- }
-
- WM_event_add_notifier(C, NC_WINDOW, NULL);
- return OPERATOR_FINISHED;
+ /* Undo System */
+ {
+ if (undoname) {
+ UndoStep *step_data = BKE_undosys_step_find_by_name(wm->undo_stack, undoname);
+ BKE_undosys_step_undo_with_data(wm->undo_stack, C, step_data);
}
- }
-
- if (sa && (sa->spacetype == SPACE_TEXT)) {
- ED_text_undo_step(C, step);
- }
- else if (obedit) {
- if (OB_TYPE_SUPPORT_EDITMODE(obedit->type)) {
- if (undoname)
- undo_editmode_name(C, undoname);
- else
- undo_editmode_step(C, step);
-
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
+ else {
+ BKE_undosys_step_undo_compat_only(wm->undo_stack, C, step);
}
}
- else {
- /* Note: we used to do a fall-through here where if the
- * mode-specific undo system had no more steps to undo (or
- * redo), the global undo would run.
- *
- * That was inconsistent with editmode, and also makes for
- * unecessarily tricky interaction with the other undo
- * systems. */
- if (obact && workspace->object_mode & OB_MODE_TEXTURE_PAINT) {
- ED_undo_paint_step(C, UNDO_PAINT_IMAGE, step, undoname);
- }
- else if (obact && workspace->object_mode & OB_MODE_SCULPT) {
- ED_undo_paint_step(C, UNDO_PAINT_MESH, step, undoname);
- }
- else if (obact && workspace->object_mode & OB_MODE_PARTICLE_EDIT) {
- if (step == 1)
- PE_undo(scene, view_layer);
- else
- PE_redo(scene, view_layer);
- }
- else if (U.uiflag & USER_GLOBALUNDO) {
- // note python defines not valid here anymore.
- //#ifdef WITH_PYTHON
- // XXX BPY_scripts_clear_pyobjects();
- //#endif
-
- /* for global undo/redo we should just clear the editmode stack */
- /* for example, texface stores image pointers */
- undo_editmode_clear();
-
- ED_viewport_render_kill_jobs(wm, bmain, true);
- if (undoname)
- BKE_undo_name(C, undoname);
- else
- BKE_undo_step(C, step);
-
- scene = CTX_data_scene(C);
-
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
- }
- }
-
WM_event_add_notifier(C, NC_WINDOW, NULL);
WM_event_add_notifier(C, NC_WM | ND_UNDO, NULL);
if (win) {
win->addmousemove = true;
}
-
+
return OPERATOR_FINISHED;
}
void ED_undo_grouped_push(bContext *C, const char *str)
{
/* do nothing if previous undo task is the same as this one (or from the same undo group) */
- const char *last_undo = BKE_undo_get_name_last();
+ {
+ wmWindowManager *wm = CTX_wm_manager(C);
+ if (wm->undo_stack->steps.last) {
+ const UndoStep *us = wm->undo_stack->steps.last;
+ if (STREQ(str, us->name)) {
+ return;
+ }
+ }
- if (last_undo && STREQ(str, last_undo)) {
- return;
}
/* push as usual */
@@ -274,48 +200,8 @@ void ED_undo_pop_op(bContext *C, wmOperator *op)
/* name optionally, function used to check for operator redo panel */
bool ED_undo_is_valid(const bContext *C, const char *undoname)
{
- const WorkSpace *workspace = CTX_wm_workspace(C);
- Object *obedit = CTX_data_edit_object(C);
- Object *obact = CTX_data_active_object(C);
- ScrArea *sa = CTX_wm_area(C);
-
- if (sa && sa->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = (SpaceImage *)sa->spacedata.first;
-
- if ((obact && (workspace->object_mode & OB_MODE_TEXTURE_PAINT)) || (sima->mode == SI_MODE_PAINT)) {
- return 1;
- }
- }
-
- if (sa && (sa->spacetype == SPACE_TEXT)) {
- return 1;
- }
- else if (obedit) {
- if (OB_TYPE_SUPPORT_EDITMODE(obedit->type)) {
- return undo_editmode_is_valid(undoname);
- }
- }
- else {
-
- /* if below tests fail, global undo gets executed */
-
- if (obact && workspace->object_mode & OB_MODE_TEXTURE_PAINT) {
- if (ED_undo_paint_is_valid(UNDO_PAINT_IMAGE, undoname))
- return 1;
- }
- else if (obact && workspace->object_mode & OB_MODE_SCULPT) {
- if (ED_undo_paint_is_valid(UNDO_PAINT_MESH, undoname))
- return 1;
- }
- else if (obact && workspace->object_mode & OB_MODE_PARTICLE_EDIT) {
- return PE_undo_is_valid(CTX_data_scene(C), CTX_data_view_layer(C));
- }
-
- if (U.uiflag & USER_GLOBALUNDO) {
- return BKE_undo_is_valid(undoname);
- }
- }
- return 0;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ return BKE_undosys_stack_has_undo(wm->undo_stack, undoname);
}
static int ed_undo_exec(bContext *C, wmOperator *UNUSED(op))
@@ -493,112 +379,45 @@ void ED_undo_operator_repeat_cb_evt(bContext *C, void *arg_op, int UNUSED(arg_ev
/* ************************** */
-enum {
- UNDOSYSTEM_GLOBAL = 1,
- UNDOSYSTEM_EDITMODE = 2,
- UNDOSYSTEM_PARTICLE = 3,
- UNDOSYSTEM_IMAPAINT = 4,
- UNDOSYSTEM_SCULPT = 5,
-};
-
-static int get_undo_system(bContext *C)
-{
- const WorkSpace *workspace = CTX_wm_workspace(C);
- Object *obact = CTX_data_active_object(C);
- Object *obedit = CTX_data_edit_object(C);
- ScrArea *sa = CTX_wm_area(C);
-
- /* first check for editor undo */
- if (sa && (sa->spacetype == SPACE_IMAGE)) {
- SpaceImage *sima = (SpaceImage *)sa->spacedata.first;
-
- if ((obact && (workspace->object_mode & OB_MODE_TEXTURE_PAINT)) || (sima->mode == SI_MODE_PAINT)) {
- if (!ED_undo_paint_empty(UNDO_PAINT_IMAGE))
- return UNDOSYSTEM_IMAPAINT;
- }
- }
- /* find out which undo system */
- if (obedit) {
- if (OB_TYPE_SUPPORT_EDITMODE(obedit->type)) {
- return UNDOSYSTEM_EDITMODE;
- }
- }
- else {
- if (obact) {
- if (workspace->object_mode & OB_MODE_PARTICLE_EDIT)
- return UNDOSYSTEM_PARTICLE;
- else if (workspace->object_mode & OB_MODE_TEXTURE_PAINT) {
- if (!ED_undo_paint_empty(UNDO_PAINT_IMAGE))
- return UNDOSYSTEM_IMAPAINT;
- }
- else if (workspace->object_mode & OB_MODE_SCULPT) {
- if (!ED_undo_paint_empty(UNDO_PAINT_MESH))
- return UNDOSYSTEM_SCULPT;
- }
- }
- if (U.uiflag & USER_GLOBALUNDO)
- return UNDOSYSTEM_GLOBAL;
- }
-
- return 0;
-}
-
/* create enum based on undo items */
-static const EnumPropertyItem *rna_undo_itemf(bContext *C, int undosys, int *totitem)
+static const EnumPropertyItem *rna_undo_itemf(bContext *C, int *totitem)
{
EnumPropertyItem item_tmp = {0}, *item = NULL;
int i = 0;
- bool active;
-
- while (true) {
- const char *name = NULL;
-
- if (undosys == UNDOSYSTEM_PARTICLE) {
- name = PE_undo_get_name(CTX_data_scene(C), CTX_data_view_layer(C), i, &active);
- }
- else if (undosys == UNDOSYSTEM_EDITMODE) {
- name = undo_editmode_get_name(C, i, &active);
- }
- else if (undosys == UNDOSYSTEM_IMAPAINT) {
- name = ED_undo_paint_get_name(C, UNDO_PAINT_IMAGE, i, &active);
- }
- else if (undosys == UNDOSYSTEM_SCULPT) {
- name = ED_undo_paint_get_name(C, UNDO_PAINT_MESH, i, &active);
- }
- else {
- name = BKE_undo_get_name(i, &active);
- }
-
- if (name) {
- item_tmp.identifier = name;
+
+ wmWindowManager *wm = CTX_wm_manager(C);
+ if (wm->undo_stack == NULL) {
+ return NULL;
+ }
+
+ for (UndoStep *us = wm->undo_stack->steps.first; us; us = us->next, i++) {
+ if (us->skip == false) {
+ item_tmp.identifier = us->name;
/* XXX This won't work with non-default contexts (e.g. operators) :/ */
- item_tmp.name = IFACE_(name);
- if (active)
+ item_tmp.name = IFACE_(us->name);
+ if (us == wm->undo_stack->step_active) {
item_tmp.icon = ICON_RESTRICT_VIEW_OFF;
- else
+ }
+ else {
item_tmp.icon = ICON_NONE;
- item_tmp.value = i++;
+ }
+ item_tmp.value = i;
RNA_enum_item_add(&item, totitem, &item_tmp);
}
- else
- break;
}
-
RNA_enum_item_end(&item, totitem);
-
+
return item;
}
static int undo_history_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- int undosys, totitem = 0;
-
- undosys = get_undo_system(C);
-
- if (undosys) {
- const EnumPropertyItem *item = rna_undo_itemf(C, undosys, &totitem);
-
+ int totitem = 0;
+
+ {
+ const EnumPropertyItem *item = rna_undo_itemf(C, &totitem);
+
if (totitem > 0) {
uiPopupMenu *pup = UI_popup_menu_begin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE);
uiLayout *layout = UI_popup_menu_layout(pup);
@@ -632,30 +451,12 @@ static int undo_history_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
/* note: also check ed_undo_step() in top if you change notifiers */
static int undo_history_exec(bContext *C, wmOperator *op)
{
- if (RNA_struct_property_is_set(op->ptr, "item")) {
- int undosys = get_undo_system(C);
- int item = RNA_int_get(op->ptr, "item");
-
- if (undosys == UNDOSYSTEM_PARTICLE) {
- PE_undo_number(CTX_data_scene(C), CTX_data_view_layer(C), item);
- }
- else if (undosys == UNDOSYSTEM_EDITMODE) {
- undo_editmode_number(C, item + 1);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
- }
- else if (undosys == UNDOSYSTEM_IMAPAINT) {
- ED_undo_paint_step_num(C, UNDO_PAINT_IMAGE, item);
- }
- else if (undosys == UNDOSYSTEM_SCULPT) {
- ED_undo_paint_step_num(C, UNDO_PAINT_MESH, item);
- }
- else {
- ED_viewport_render_kill_jobs(CTX_wm_manager(C), CTX_data_main(C), true);
- BKE_undo_number(C, item);
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, CTX_data_scene(C));
- }
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "item");
+ if (RNA_property_is_set(op->ptr, prop)) {
+ int item = RNA_property_int_get(op->ptr, prop);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ BKE_undosys_step_undo_from_index(wm->undo_stack, C, item);
WM_event_add_notifier(C, NC_WINDOW, NULL);
-
return OPERATOR_FINISHED;
}
return OPERATOR_CANCELLED;
diff --git a/source/blender/editors/util/undo_system_types.c b/source/blender/editors/util/undo_system_types.c
new file mode 100644
index 00000000000..a326d9eb859
--- /dev/null
+++ b/source/blender/editors/util/undo_system_types.c
@@ -0,0 +1,74 @@
+/*
+ * ***** 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 *****
+ */
+
+/** \file blender/editors/util/undo_system_types.c
+ * \ingroup edutil
+ */
+
+#include <string.h>
+
+#include "BLI_utildefines.h"
+
+
+#include "ED_armature.h"
+#include "ED_curve.h"
+#include "ED_lattice.h"
+#include "ED_mball.h"
+#include "ED_mesh.h"
+#include "ED_paint.h"
+#include "ED_particle.h"
+#include "ED_sculpt.h"
+#include "ED_text.h"
+#include "ED_util.h"
+#include "util_intern.h"
+
+/* Keep last */
+#include "BKE_undo_system.h"
+
+void ED_undosys_type_init(void)
+{
+ /* Edit Modes */
+ BKE_undosys_type_append(ED_armature_undosys_type);
+ BKE_undosys_type_append(ED_curve_undosys_type);
+ BKE_undosys_type_append(ED_font_undosys_type);
+ BKE_undosys_type_append(ED_lattice_undosys_type);
+ BKE_undosys_type_append(ED_mball_undosys_type);
+ BKE_undosys_type_append(ED_mesh_undosys_type);
+
+ /* Paint Modes */
+ BKE_UNDOSYS_TYPE_IMAGE = BKE_undosys_type_append(ED_image_undosys_type);
+
+ BKE_UNDOSYS_TYPE_SCULPT = BKE_undosys_type_append(ED_sculpt_undosys_type);
+
+ BKE_UNDOSYS_TYPE_PARTICLE = BKE_undosys_type_append(ED_particle_undosys_type);
+
+ BKE_UNDOSYS_TYPE_PAINTCURVE = BKE_undosys_type_append(ED_paintcurve_undosys_type);
+
+ /* Text editor */
+ BKE_undosys_type_append(ED_text_undosys_type);
+
+ /* Keep global undo last (as a fallback). */
+ BKE_UNDOSYS_TYPE_MEMFILE = BKE_undosys_type_append(ED_memfile_undosys_type);
+}
+
+void ED_undosys_type_free(void)
+{
+ BKE_undosys_type_free_all();
+}
diff --git a/source/blender/editors/util/util_intern.h b/source/blender/editors/util/util_intern.h
index 0f650330951..6eda3900e91 100644
--- a/source/blender/editors/util/util_intern.h
+++ b/source/blender/editors/util/util_intern.h
@@ -34,13 +34,11 @@
/* internal exports only */
-/* editmode_undo.c */
-void undo_editmode_name(struct bContext *C, const char *undoname);
-bool undo_editmode_is_valid(const char *undoname);
-const char *undo_editmode_get_name(struct bContext *C, int nr, bool *r_active);
-void *undo_editmode_get_prev(struct Object *ob);
-void undo_editmode_step(struct bContext *C, int step);
-void undo_editmode_number(struct bContext *C, int nr);
+struct UndoType;
+struct Main;
+struct Scene;
-#endif /* __UTIL_INTERN_H__ */
+/* memfile_undo.c */
+void ED_memfile_undosys_type(struct UndoType *ut);
+#endif /* __UTIL_INTERN_H__ */