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:
-rw-r--r--source/blender/blenlib/intern/boxpack2d.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_log.c46
-rw-r--r--source/blender/bmesh/intern/bmesh_log.h3
-rw-r--r--source/blender/editors/include/ED_sculpt.h2
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h1
-rw-r--r--source/blender/editors/sculpt_paint/paint_undo.c47
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_undo.c22
-rw-r--r--source/blender/editors/space_image/image_ops.c2
-rw-r--r--source/blender/editors/util/undo.c2
11 files changed, 117 insertions, 14 deletions
diff --git a/source/blender/blenlib/intern/boxpack2d.c b/source/blender/blenlib/intern/boxpack2d.c
index 5d01706ebb1..91495ce3c9c 100644
--- a/source/blender/blenlib/intern/boxpack2d.c
+++ b/source/blender/blenlib/intern/boxpack2d.c
@@ -91,7 +91,7 @@ typedef struct BoxVert {
BLI_INLINE int quad_flag(unsigned int q)
{
- BLI_assert(q < 4 && q >= 0);
+ BLI_assert(q < 4);
return (1 << q);
}
diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c
index 7d3bc0e16b3..0bb1a892ffe 100644
--- a/source/blender/bmesh/intern/bmesh_log.c
+++ b/source/blender/bmesh/intern/bmesh_log.c
@@ -489,6 +489,29 @@ BMLog *BM_log_create(BMesh *bm)
return log;
}
+void BM_log_cleanup_entry(BMLogEntry *entry)
+{
+ BMLog *log = entry->log;
+
+ if (log) {
+ /* Take all used IDs */
+ bm_log_id_ghash_retake(log->unused_ids, entry->deleted_verts);
+ bm_log_id_ghash_retake(log->unused_ids, entry->deleted_faces);
+ bm_log_id_ghash_retake(log->unused_ids, entry->added_verts);
+ bm_log_id_ghash_retake(log->unused_ids, entry->added_faces);
+ bm_log_id_ghash_retake(log->unused_ids, entry->modified_verts);
+ bm_log_id_ghash_retake(log->unused_ids, entry->modified_faces);
+
+ /* delete entries to avoid releasing ids in node cleanup */
+ BLI_ghash_clear(entry->deleted_verts, NULL, NULL);
+ BLI_ghash_clear(entry->deleted_faces, NULL, NULL);
+ BLI_ghash_clear(entry->added_verts, NULL, NULL);
+ BLI_ghash_clear(entry->added_faces, NULL, NULL);
+ BLI_ghash_clear(entry->modified_verts, NULL, NULL);
+ }
+}
+
+
/* Allocate and initialize a new BMLog using existing BMLogEntries
*
* The 'entry' should be the last entry in the BMLog. Its prev pointer
@@ -684,8 +707,27 @@ void BM_log_entry_drop(BMLogEntry *entry)
* entry. Since the entry is at the beginning of the undo
* stack, and it's being deleted, those elements can never be
* restored. Their IDs can go back into the pool. */
- bm_log_id_ghash_release(log, entry->deleted_faces);
- bm_log_id_ghash_release(log, entry->deleted_verts);
+
+ /* This would never happen usually since first entry of log is
+ * usually dyntopo enable, which, when reverted will free the log
+ * completely. However, it is possible have a stroke instead of
+ * dyntopo enable as first entry if nodes have been cleaned up
+ * after sculpting on a different object than A, B.
+ *
+ * The steps are:
+ * A dyntopo enable - sculpt
+ * B dyntopo enable - sculpt - undo (A objects operators get cleaned up)
+ * A sculpt (now A's log has a sculpt operator as first entry)
+ *
+ * Causing a cleanup at this point will call the code below, however
+ * this will invalidate the state of the log since the deleted vertices
+ * have been reclaimed already on step 2 (see BM_log_cleanup_entry)
+ *
+ * Also, design wise, a first entry should not have any deleted vertices since it
+ * should not have anything to delete them -from-
+ */
+ //bm_log_id_ghash_release(log, entry->deleted_faces);
+ //bm_log_id_ghash_release(log, entry->deleted_verts);
}
else if (!entry->next) {
/* Release IDs of elements that are added by this entry. Since
diff --git a/source/blender/bmesh/intern/bmesh_log.h b/source/blender/bmesh/intern/bmesh_log.h
index 7a26506439f..2147b5c64b4 100644
--- a/source/blender/bmesh/intern/bmesh_log.h
+++ b/source/blender/bmesh/intern/bmesh_log.h
@@ -51,6 +51,9 @@ void BM_log_mesh_elems_reorder(BMesh *bm, BMLog *log);
/* Start a new log entry and update the log entry list */
BMLogEntry *BM_log_entry_add(BMLog *log);
+/* Mark all used ids as unused for this node */
+void BM_log_cleanup_entry(BMLogEntry *entry);
+
/* Remove an entry from the log */
void BM_log_entry_drop(BMLogEntry *entry);
diff --git a/source/blender/editors/include/ED_sculpt.h b/source/blender/editors/include/ED_sculpt.h
index 8fcb228803b..e89b0c53a10 100644
--- a/source/blender/editors/include/ED_sculpt.h
+++ b/source/blender/editors/include/ED_sculpt.h
@@ -61,7 +61,7 @@ typedef void (*UndoFreeCb)(struct ListBase *lb);
int ED_undo_paint_step(struct bContext *C, int type, int step, const char *name);
void ED_undo_paint_step_num(struct bContext *C, int type, int num);
-const char *ED_undo_paint_get_name(int type, int nr, int *active);
+const char *ED_undo_paint_get_name(struct bContext *C, int type, int nr, int *active);
void ED_undo_paint_free(void);
int ED_undo_paint_valid(int type, const char *name);
bool ED_undo_paint_empty(int type);
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 5e2bdcb3c93..575b7fc4062 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -491,7 +491,7 @@ static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, float mou
settings->imapaint.flag |= IMAGEPAINT_DRAWING;
ED_undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
- ED_image_undo_restore, ED_image_undo_free);
+ ED_image_undo_restore, ED_image_undo_free);
{
UnifiedPaintSettings *ups = &settings->unified_paint_settings;
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 492857bd0bb..f69c7e0ed41 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -4337,7 +4337,7 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
scene->toolsettings->imapaint.flag |= IMAGEPAINT_DRAWING;
ED_undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
- ED_image_undo_restore, ED_image_undo_free);
+ ED_image_undo_restore, ED_image_undo_free);
/* allocate and initialize spatial data structures */
project_paint_begin(&ps);
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index d8f7a3d8e05..b420c8d209c 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -229,6 +229,7 @@ typedef enum BrushStrokeMode {
/* paint_undo.c */
struct ListBase *undo_paint_push_get_list(int type);
void undo_paint_push_count_alloc(int type, int size);
+bool sculpt_undo_cleanup(struct bContext *C, struct ListBase *lb);
/* paint_hide.c */
diff --git a/source/blender/editors/sculpt_paint/paint_undo.c b/source/blender/editors/sculpt_paint/paint_undo.c
index f3946e30b83..5bd6526c270 100644
--- a/source/blender/editors/sculpt_paint/paint_undo.c
+++ b/source/blender/editors/sculpt_paint/paint_undo.c
@@ -53,14 +53,17 @@ typedef struct UndoElem {
UndoFreeCb free;
} UndoElem;
+typedef bool (*UndoCleanupCb)(struct bContext *C, ListBase *lb);
+
typedef struct UndoStack {
int type;
ListBase elems;
UndoElem *current;
+ UndoCleanupCb cleanup;
} UndoStack;
-static UndoStack ImageUndoStack = {UNDO_PAINT_IMAGE, {NULL, NULL}, NULL};
-static UndoStack MeshUndoStack = {UNDO_PAINT_MESH, {NULL, NULL}, NULL};
+static UndoStack ImageUndoStack = {UNDO_PAINT_IMAGE, {NULL, NULL}, NULL, NULL};
+static UndoStack MeshUndoStack = {UNDO_PAINT_MESH, {NULL, NULL}, NULL, sculpt_undo_cleanup};
/* Generic */
@@ -171,10 +174,39 @@ static void undo_stack_push_end(UndoStack *stack)
}
}
+static void undo_stack_cleanup(UndoStack *stack, bContext *C)
+{
+ UndoElem *uel = stack->elems.first;
+ bool stack_reset = false;
+
+ if (stack->cleanup) {
+ while (uel) {
+ if (stack->cleanup(C, &uel->elems)) {
+ UndoElem *uel_tmp = uel->next;
+ if (stack->current == uel) {
+ stack->current = NULL;
+ stack_reset = true;
+ }
+ undo_elem_free(stack, uel);
+ BLI_freelinkN(&stack->elems, uel);
+ uel = uel_tmp;
+ }
+ else
+ uel = uel->next;
+ }
+ if (stack_reset) {
+ stack->current = stack->elems.last;
+ }
+ }
+}
+
static int undo_stack_step(bContext *C, UndoStack *stack, int step, const char *name)
{
UndoElem *undo;
+ /* first cleanup any old undo steps that may belong to invalid data */
+ undo_stack_cleanup(stack, C);
+
if (step == 1) {
if (stack->current == NULL) {
/* pass */
@@ -315,12 +347,17 @@ static char *undo_stack_get_name(UndoStack *stack, int nr, int *active)
return NULL;
}
-const char *ED_undo_paint_get_name(int type, int nr, int *active)
+const char *ED_undo_paint_get_name(bContext *C, int type, int nr, int *active)
{
- if (type == UNDO_PAINT_IMAGE)
+
+ if (type == UNDO_PAINT_IMAGE) {
+ undo_stack_cleanup(&ImageUndoStack, C);
return undo_stack_get_name(&ImageUndoStack, nr, active);
- else if (type == UNDO_PAINT_MESH)
+ }
+ else if (type == UNDO_PAINT_MESH) {
+ undo_stack_cleanup(&MeshUndoStack, C);
return undo_stack_get_name(&MeshUndoStack, nr, active);
+ }
return NULL;
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index 57e852db796..9beb11ec2f4 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -526,9 +526,11 @@ static void sculpt_undo_free(ListBase *lb)
}
if (unode->mask)
MEM_freeN(unode->mask);
+
if (unode->bm_entry) {
BM_log_entry_drop(unode->bm_entry);
}
+
if (unode->bm_enter_totvert)
CustomData_free(&unode->bm_enter_vdata, unode->bm_enter_totvert);
if (unode->bm_enter_totedge)
@@ -540,6 +542,24 @@ static void sculpt_undo_free(ListBase *lb)
}
}
+bool sculpt_undo_cleanup(bContext *C, ListBase *lb) {
+ Object *ob = CTX_data_active_object(C);
+ SculptUndoNode *unode;
+
+ unode = lb->first;
+
+ if (strcmp(unode->idname, ob->id.name) != 0) {
+ for (unode = lb->first; unode; unode = unode->next) {
+ if (unode->bm_entry)
+ BM_log_cleanup_entry(unode->bm_entry);
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
SculptUndoNode *sculpt_undo_get_node(PBVHNode *node)
{
ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_MESH);
@@ -859,7 +879,7 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node,
void sculpt_undo_push_begin(const char *name)
{
ED_undo_paint_push_begin(UNDO_PAINT_MESH, name,
- sculpt_undo_restore, sculpt_undo_free);
+ sculpt_undo_restore, sculpt_undo_free);
}
void sculpt_undo_push_end(void)
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 57be15f23fb..6f42a0b8928 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -2034,7 +2034,7 @@ static int image_invert_exec(bContext *C, wmOperator *op)
if (support_undo) {
ED_undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
- ED_image_undo_restore, ED_image_undo_free);
+ ED_image_undo_restore, ED_image_undo_free);
/* not strictly needed, because we only imapaint_dirty_region to invalidate all tiles
* but better do this right in case someone copies this for a tool that uses partial redraw better */
ED_imapaint_clear_partial_redraw();
diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c
index a4f2c36f250..4d14323a20b 100644
--- a/source/blender/editors/util/undo.c
+++ b/source/blender/editors/util/undo.c
@@ -489,7 +489,7 @@ static EnumPropertyItem *rna_undo_itemf(bContext *C, int undosys, int *totitem)
name = undo_editmode_get_name(C, i, &active);
}
else if (undosys == UNDOSYSTEM_IMAPAINT) {
- name = ED_undo_paint_get_name(UNDO_PAINT_IMAGE, i, &active);
+ name = ED_undo_paint_get_name(C, UNDO_PAINT_IMAGE, i, &active);
}
else {
name = BKE_undo_get_name(i, &active);