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>2019-02-05 06:24:11 +0300
committerCampbell Barton <ideasman42@gmail.com>2019-02-06 03:52:04 +0300
commite535ff44ffd686def7aafec401acec657f5a614c (patch)
tree39910c4513dd223378f71af51730fae3a62ac3ae /source/blender/editors/sculpt_paint/paint_image_undo.c
parent8996e26116f063ce28a9784899fc36d87f31dabe (diff)
Undo System: remove accumulate/store modes
This complicated handling of undo steps in a generic way especially switching between undo systems that stored data to ones that accumulated changes. Now each undo system must treat it's steps as check-point, internally it can apply/rewind changes. This commit also fixes projection paint where the object mode wasn't following the undo steps.
Diffstat (limited to 'source/blender/editors/sculpt_paint/paint_image_undo.c')
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_undo.c145
1 files changed, 114 insertions, 31 deletions
diff --git a/source/blender/editors/sculpt_paint/paint_image_undo.c b/source/blender/editors/sculpt_paint/paint_image_undo.c
index 04d58877608..20696ed1e91 100644
--- a/source/blender/editors/sculpt_paint/paint_image_undo.c
+++ b/source/blender/editors/sculpt_paint/paint_image_undo.c
@@ -36,6 +36,7 @@
#include "BKE_context.h"
#include "BKE_image.h"
+#include "BKE_paint.h"
#include "BKE_undo_system.h"
#include "DEG_depsgraph.h"
@@ -43,6 +44,7 @@
#include "ED_paint.h"
#include "ED_undo.h"
#include "ED_util.h"
+#include "ED_object.h"
#include "GPU_draw.h"
@@ -349,19 +351,6 @@ static void image_undo_free_list(ListBase *lb)
}
}
-void ED_image_undo_push_begin(const char *name)
-{
- UndoStack *ustack = ED_undo_stack_get();
- bContext *C = NULL; /* special case, we never read from this. */
- BKE_undosys_step_push_init_with_type(ustack, C, name, BKE_UNDOSYS_TYPE_IMAGE);
-}
-
-void ED_image_undo_push_end(void)
-{
- UndoStack *ustack = ED_undo_stack_get();
- BKE_undosys_step_push(ustack, NULL, NULL);
-}
-
static void image_undo_invalidate(void)
{
UndoImageTile *tile;
@@ -381,6 +370,8 @@ static void image_undo_invalidate(void)
typedef struct ImageUndoStep {
UndoStep step;
ListBase tiles;
+ bool is_encode_init;
+ ePaintMode paint_mode;
/* Use for all ID lookups (can be NULL). */
struct UndoIDPtrMap *id_map;
@@ -432,10 +423,11 @@ static void image_undosys_step_encode_init(struct bContext *UNUSED(C), UndoStep
{
ImageUndoStep *us = (ImageUndoStep *)us_p;
/* dummy, memory is cleared anyway. */
+ us->is_encode_init = true;
BLI_listbase_clear(&us->tiles);
}
-static bool image_undosys_step_encode(struct bContext *UNUSED(C), struct Main *UNUSED(bmain), UndoStep *us_p)
+static bool image_undosys_step_encode(struct bContext *C, struct Main *UNUSED(bmain), UndoStep *us_p)
{
/* dummy, encoding is done along the way by adding tiles
* to the current 'ImageUndoStep' added by encode_init. */
@@ -445,33 +437,100 @@ static bool image_undosys_step_encode(struct bContext *UNUSED(C), struct Main *U
int allocsize = IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE * 4;
-
- /* first dispose of invalid tiles (may happen due to drag dot for instance) */
- for (UndoImageTile *tile = us->tiles.first; tile;) {
- if (!tile->valid) {
- UndoImageTile *tmp_tile = tile->next;
- MEM_freeN(tile->rect.pt);
- BLI_freelinkN(&us->tiles, tile);
- tile = tmp_tile;
- }
- else {
- us->step.data_size += allocsize * ((tile->use_float) ? sizeof(float) : sizeof(char));
- tile = tile->next;
+ if (us->is_encode_init) {
+ /* first dispose of invalid tiles (may happen due to drag dot for instance) */
+ for (UndoImageTile *tile = us->tiles.first; tile;) {
+ if (!tile->valid) {
+ UndoImageTile *tmp_tile = tile->next;
+ MEM_freeN(tile->rect.pt);
+ BLI_freelinkN(&us->tiles, tile);
+ tile = tmp_tile;
+ }
+ else {
+ us->step.data_size += allocsize * ((tile->use_float) ? sizeof(float) : sizeof(char));
+ tile = tile->next;
+ }
}
}
+ else {
+ /* Happens when switching modes. */
+ ePaintMode paint_mode = BKE_paintmode_get_active_from_context(C);
+ BLI_assert(ELEM(paint_mode, PAINT_MODE_TEXTURE_2D, PAINT_MODE_TEXTURE_3D));
+ us->paint_mode = paint_mode;
+ }
image_undosys_step_encode_store_ids(us);
+ us_p->is_applied = true;
+
return true;
}
-static void image_undosys_step_decode(struct bContext *UNUSED(C), struct Main *bmain, UndoStep *us_p, int UNUSED(dir))
+
+static void image_undosys_step_decode_undo_impl(ImageUndoStep *us)
+{
+ BLI_assert(us->step.is_applied == true);
+ image_undo_restore_list(&us->tiles, us->id_map);
+ us->step.is_applied = false;
+}
+
+static void image_undosys_step_decode_redo_impl(ImageUndoStep *us)
+{
+ BLI_assert(us->step.is_applied == false);
+ image_undo_restore_list(&us->tiles, us->id_map);
+ us->step.is_applied = true;
+}
+
+static void image_undosys_step_decode_undo(ImageUndoStep *us)
+{
+ ImageUndoStep *us_iter = us;
+ while (us_iter->step.next && (us_iter->step.next->type == us_iter->step.type)) {
+ if (us_iter->step.next->is_applied == false) {
+ break;
+ }
+ us_iter = (ImageUndoStep *)us_iter->step.next;
+ }
+ while (us_iter != us) {
+ image_undosys_step_decode_undo_impl(us_iter);
+ us_iter = (ImageUndoStep *)us_iter->step.prev;
+ }
+}
+
+static void image_undosys_step_decode_redo(ImageUndoStep *us)
+{
+ ImageUndoStep *us_iter = us;
+ while (us_iter->step.prev && (us_iter->step.prev->type == us_iter->step.type)) {
+ if (us_iter->step.prev->is_applied == true) {
+ break;
+ }
+ us_iter = (ImageUndoStep *)us_iter->step.prev;
+ }
+ while (us_iter && (us_iter->step.is_applied == false)) {
+ image_undosys_step_decode_redo_impl(us_iter);
+ if (us_iter == us) {
+ break;
+ }
+ us_iter = (ImageUndoStep *)us_iter->step.next;
+ }
+}
+
+static void image_undosys_step_decode(struct bContext *C, struct Main *bmain, UndoStep *us_p, int dir)
{
ImageUndoStep *us = (ImageUndoStep *)us_p;
#if 0
paint_undosys_step_decode_restore_ids(us);
#endif
- image_undo_restore_list(&us->tiles, us->id_map);
+
+ if (dir < 0) {
+ image_undosys_step_decode_undo(us);
+ }
+ else {
+ image_undosys_step_decode_redo(us);
+ }
+
+ if (us->paint_mode == PAINT_MODE_TEXTURE_3D) {
+ ED_object_mode_set(C, OB_MODE_TEXTURE_PAINT);
+ }
/* Refresh texture slots. */
ED_editors_init_for_undo(bmain);
@@ -505,7 +564,6 @@ void ED_image_undosys_type(UndoType *ut)
ut->step_foreach_ID_ref = image_undosys_foreach_ID_ref;
- ut->mode = BKE_UNDOTYPE_MODE_ACCUMULATE;
ut->use_context = true;
ut->step_size = sizeof(ImageUndoStep);
@@ -527,8 +585,17 @@ ListBase *ED_image_undosys_step_get_tiles(UndoStep *us_p)
ListBase *ED_image_undo_get_tiles(void)
{
UndoStack *ustack = ED_undo_stack_get();
- UndoStep *us = BKE_undosys_stack_init_or_active_with_type(ustack, BKE_UNDOSYS_TYPE_IMAGE);
- return ED_image_undosys_step_get_tiles(us);
+ UndoStep *us_prev = ustack->step_init;
+ UndoStep *us_p = BKE_undosys_stack_init_or_active_with_type(ustack, BKE_UNDOSYS_TYPE_IMAGE);
+ ImageUndoStep *us = (ImageUndoStep *)us_p;
+ /* We should always have an undo push started when accessing tiles,
+ * not doing this means we won't have paint_mode correctly set. */
+ BLI_assert(us_p == us_prev);
+ if (us_p != us_prev) {
+ /* Fallback value until we can be sure this never happens. */
+ us->paint_mode = PAINT_MODE_TEXTURE_2D;
+ }
+ return ED_image_undosys_step_get_tiles(us_p);
}
/* restore painting image to previous state. Used for anchored and drag-dot style brushes*/
@@ -539,4 +606,20 @@ void ED_image_undo_restore(UndoStep *us)
image_undo_invalidate();
}
+void ED_image_undo_push_begin(const char *name, int paint_mode)
+{
+ UndoStack *ustack = ED_undo_stack_get();
+ bContext *C = NULL; /* special case, we never read from this. */
+ UndoStep *us_p = BKE_undosys_step_push_init_with_type(ustack, C, name, BKE_UNDOSYS_TYPE_IMAGE);
+ ImageUndoStep *us = (ImageUndoStep *)us_p;
+ BLI_assert(ELEM(paint_mode, PAINT_MODE_TEXTURE_2D, PAINT_MODE_TEXTURE_3D));
+ us->paint_mode = paint_mode;
+}
+
+void ED_image_undo_push_end(void)
+{
+ UndoStack *ustack = ED_undo_stack_get();
+ BKE_undosys_step_push(ustack, NULL, NULL);
+}
+
/** \} */