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:
Diffstat (limited to 'source/blender/editors/undo')
-rw-r--r--source/blender/editors/undo/ed_undo.c53
-rw-r--r--source/blender/editors/undo/memfile_undo.c38
2 files changed, 62 insertions, 29 deletions
diff --git a/source/blender/editors/undo/ed_undo.c b/source/blender/editors/undo/ed_undo.c
index 123fd5f35da..6633e1c427c 100644
--- a/source/blender/editors/undo/ed_undo.c
+++ b/source/blender/editors/undo/ed_undo.c
@@ -79,15 +79,26 @@ static CLG_LogRef LOG = {"ed.undo"};
void ED_undo_push(bContext *C, const char *str)
{
CLOG_INFO(&LOG, 1, "name='%s'", str);
+ WM_file_tag_modified();
- const int steps = U.undosteps;
-
+ wmWindowManager *wm = CTX_wm_manager(C);
+ int steps = U.undosteps;
+
+ /* Ensure steps that have been initialized are always pushed,
+ * even when undo steps are zero.
+ *
+ * Note that some modes (paint, sculpt) initialize an undo step before an action runs,
+ * then accumulate changes there, or restore data from it in the case of 2D painting.
+ *
+ * For this reason we need to handle the undo step even when undo steps is set to zero.
+ */
+ if ((steps <= 0) && wm->undo_stack->step_init != NULL) {
+ steps = 1;
+ }
if (steps <= 0) {
return;
}
- 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);
@@ -97,14 +108,12 @@ void ED_undo_push(bContext *C, const char *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);
+ BKE_undosys_stack_limit_steps_and_memory(wm->undo_stack, -1, memory_limit);
}
if (CLOG_CHECK(&LOG, 1)) {
BKE_undosys_print(wm->undo_stack);
}
-
- WM_file_tag_modified();
}
/**
@@ -119,7 +128,7 @@ static int ed_undo_step_impl(
CLOG_INFO(&LOG, 1, "name='%s', step=%d", undoname, step);
wmWindowManager *wm = CTX_wm_manager(C);
Scene *scene = CTX_data_scene(C);
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = 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 */
@@ -138,7 +147,7 @@ static int ed_undo_step_impl(
if (ED_gpencil_session_active()) {
return ED_undo_gpencil_step(C, step, undoname);
}
- if (sa && (sa->spacetype == SPACE_VIEW3D)) {
+ if (area && (area->spacetype == SPACE_VIEW3D)) {
Object *obact = CTX_data_active_object(C);
if (obact && (obact->type == OB_GPENCIL)) {
ED_gpencil_toggle_brush_cursor(C, false, NULL);
@@ -195,7 +204,7 @@ static int ed_undo_step_impl(
}
/* Set special modes for grease pencil */
- if (sa && (sa->spacetype == SPACE_VIEW3D)) {
+ if (area && (area->spacetype == SPACE_VIEW3D)) {
Object *obact = CTX_data_active_object(C);
if (obact && (obact->type == OB_GPENCIL)) {
/* set cursor */
@@ -558,11 +567,11 @@ int ED_undo_operator_repeat(bContext *C, wmOperator *op)
struct Scene *scene = CTX_data_scene(C);
/* keep in sync with logic in view3d_panel_operator_redo() */
- ARegion *ar_orig = CTX_wm_region(C);
- ARegion *ar_win = BKE_area_find_region_active_win(CTX_wm_area(C));
+ ARegion *region_orig = CTX_wm_region(C);
+ ARegion *region_win = BKE_area_find_region_active_win(CTX_wm_area(C));
- if (ar_win) {
- CTX_wm_region_set(C, ar_win);
+ if (region_win) {
+ CTX_wm_region_set(C, region_win);
}
if ((WM_operator_repeat_check(C, op)) && (WM_operator_poll(C, op->type)) &&
@@ -585,9 +594,9 @@ int ED_undo_operator_repeat(bContext *C, wmOperator *op)
if (op->type->check) {
if (op->type->check(C, op)) {
/* check for popup and re-layout buttons */
- ARegion *ar_menu = CTX_wm_menu(C);
- if (ar_menu) {
- ED_region_tag_refresh_ui(ar_menu);
+ ARegion *region_menu = CTX_wm_menu(C);
+ if (region_menu) {
+ ED_region_tag_refresh_ui(region_menu);
}
}
}
@@ -610,7 +619,7 @@ int ED_undo_operator_repeat(bContext *C, wmOperator *op)
}
/* set region back */
- CTX_wm_region_set(C, ar_orig);
+ CTX_wm_region_set(C, region_orig);
}
else {
CLOG_WARN(&LOG, "called with NULL 'op'");
@@ -816,7 +825,7 @@ static int undo_editmode_objects_from_view_layer_prepare(ViewLayer *view_layer,
{
const short object_type = obact->type;
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
Object *ob = base->object;
if ((ob->type == object_type) && (ob->mode & OB_MODE_EDIT)) {
ID *id = ob->data;
@@ -825,7 +834,7 @@ static int undo_editmode_objects_from_view_layer_prepare(ViewLayer *view_layer,
}
int len = 0;
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
Object *ob = base->object;
if ((ob->type == object_type) && (ob->mode & OB_MODE_EDIT)) {
if (ob == obact) {
@@ -852,7 +861,7 @@ Object **ED_undo_editmode_objects_from_view_layer(ViewLayer *view_layer, uint *r
const short object_type = obact->type;
int i = 0;
Object **objects = MEM_malloc_arrayN(len, sizeof(*objects), __func__);
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
Object *ob = base->object;
if ((ob->type == object_type) && (ob->mode & OB_MODE_EDIT)) {
ID *id = ob->data;
@@ -881,7 +890,7 @@ Base **ED_undo_editmode_bases_from_view_layer(ViewLayer *view_layer, uint *r_len
const short object_type = obact->type;
int i = 0;
Base **base_array = MEM_malloc_arrayN(len, sizeof(*base_array), __func__);
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
Object *ob = base->object;
if ((ob->type == object_type) && (ob->mode & OB_MODE_EDIT)) {
ID *id = ob->data;
diff --git a/source/blender/editors/undo/memfile_undo.c b/source/blender/editors/undo/memfile_undo.c
index 086aa6c4c9d..2df26abe8b3 100644
--- a/source/blender/editors/undo/memfile_undo.c
+++ b/source/blender/editors/undo/memfile_undo.c
@@ -25,14 +25,17 @@
#include "BLI_ghash.h"
+#include "DNA_node_types.h"
#include "DNA_object_enums.h"
#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "BKE_blender_undo.h"
#include "BKE_context.h"
#include "BKE_lib_id.h"
#include "BKE_lib_query.h"
#include "BKE_main.h"
+#include "BKE_node.h"
#include "BKE_scene.h"
#include "BKE_undo_system.h"
@@ -106,7 +109,6 @@ static int memfile_undosys_step_id_reused_cb(LibraryIDLinkCallbackData *cb_data)
ID *id_self = cb_data->id_self;
ID **id_pointer = cb_data->id_pointer;
BLI_assert((id_self->tag & LIB_TAG_UNDO_OLD_ID_REUSED) != 0);
- Main *bmain = cb_data->user_data;
ID *id = *id_pointer;
if (id != NULL && id->lib == NULL && (id->tag & LIB_TAG_UNDO_OLD_ID_REUSED) == 0) {
@@ -129,9 +131,6 @@ static int memfile_undosys_step_id_reused_cb(LibraryIDLinkCallbackData *cb_data)
}
}
- /* In case an old, re-used ID is using a newly read data-block (i.e. one of its ID pointers got
- * updated), we have to tell the depsgraph about it. */
- DEG_id_tag_update_ex(bmain, id_self, ID_RECALC_COPY_ON_WRITE);
return do_stop_iter ? IDWALK_RET_STOP_ITER : IDWALK_RET_NOP;
}
@@ -148,7 +147,7 @@ static void memfile_undosys_step_decode(struct bContext *C,
bool use_old_bmain_data = true;
- if (!U.experimental.use_undo_speedup) {
+ if (USER_EXPERIMENTAL_TEST(&U, use_undo_legacy)) {
use_old_bmain_data = false;
}
else if (undo_direction > 0) {
@@ -217,12 +216,37 @@ static void memfile_undosys_step_decode(struct bContext *C,
FOREACH_MAIN_ID_BEGIN (bmain, id) {
if (id->tag & LIB_TAG_UNDO_OLD_ID_REUSED) {
BKE_library_foreach_ID_link(
- bmain, id, memfile_undosys_step_id_reused_cb, bmain, IDWALK_READONLY);
+ bmain, id, memfile_undosys_step_id_reused_cb, NULL, IDWALK_READONLY);
+ }
+
+ /* Tag depsgraph to update data-block for changes that happened between the
+ * current and the target state, see direct_link_id_restore_recalc(). */
+ if (id->recalc) {
+ DEG_id_tag_update_ex(bmain, id, id->recalc);
}
}
FOREACH_MAIN_ID_END;
- BKE_main_id_tag_all(bmain, LIB_TAG_UNDO_OLD_ID_REUSED, false);
+ FOREACH_MAIN_ID_BEGIN (bmain, id) {
+ /* Clear temporary tag. */
+ id->tag &= ~LIB_TAG_UNDO_OLD_ID_REUSED;
+
+ /* We only start accumulating from this point, any tags set up to here
+ * are already part of the current undo state. This is done in a second
+ * loop because DEG_id_tag_update may set tags on other datablocks. */
+ id->recalc_after_undo_push = 0;
+ bNodeTree *nodetree = ntreeFromID(id);
+ if (nodetree != NULL) {
+ nodetree->id.recalc_after_undo_push = 0;
+ }
+ if (GS(id->name) == ID_SCE) {
+ Scene *scene = (Scene *)id;
+ if (scene->master_collection != NULL) {
+ scene->master_collection->id.recalc_after_undo_push = 0;
+ }
+ }
+ }
+ FOREACH_MAIN_ID_END;
}
WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, CTX_data_scene(C));