Added a new undonode for the silhouette operator.
authorSebastian Witt <sebastian.witt@rwth-aachen.de>
Fri, 21 Jul 2017 11:12:24 +0000 (13:12 +0200)
committerSebastian Witt <sebastian.witt@rwth-aachen.de>
Fri, 21 Jul 2017 11:12:24 +0000 (13:12 +0200)
Bare basics of undo now work, Redo can cause a crash and still needs to be implemented.
Fixed crash when stroke with < 3 points was drawn.

source/blender/editors/sculpt_paint/sculpt.c
source/blender/editors/sculpt_paint/sculpt_intern.h
source/blender/editors/sculpt_paint/sculpt_undo.c

index 49cc2e1396402f46c80c27a4eea95077d0b85c9c..b2c18217f3530a0cab3f8238beceaaf4ed8bff94 100644 (file)
@@ -5152,7 +5152,7 @@ static void silhouette_set_ref_plane(SilhouetteData *sil)
        ED_view3d_global_to_vector(sil->ar->regiondata, sil->anchor, sil->z_vec);
 }
 
-static void sculpt_silhouette_stroke_update(bContext *C, float mouse[2], SilhouetteData *sil)
+static void sculpt_silhouette_stroke_update(float mouse[2], SilhouetteData *sil)
 {
        float anchor[3];
        silhouette_set_ref_plane(sil);
@@ -6608,7 +6608,7 @@ static bool calc_stroke_normal_ori(SilhouetteStroke *stroke, float z_vec[3]) {
 }
 
 /* Generates a 3D shape from a stroke. */
-static void silhouette_create_shape_mesh(bContext *C, Mesh *me, SilhouetteData *sil, SilhouetteStroke *stroke)
+static void silhouette_create_shape_mesh(bContext *UNUSED(C), Mesh *me, SilhouetteData *sil, SilhouetteStroke *stroke)
 {
        float z_vec[3] = {0.0f,0.0f,1.0f};
        float depth = sil->depth;
@@ -6662,7 +6662,7 @@ static void silhouette_create_shape_mesh(bContext *C, Mesh *me, SilhouetteData *
 
        free_spine(spine);
 
-       ED_mesh_update(me, C, 1, 1);
+       /*ED_mesh_update(me, C, 1, 1);*/
 }
 
 /* Adds additional points to the stroke if start and end are far apart. */
@@ -6695,20 +6695,21 @@ static void sculpt_silhouette_calc_mesh(bContext *C, wmOperator *op)
        Mesh *me = ob->data;
 
        SilhouetteStroke *stroke = sil->current_stroke;
+
        stroke_smooth_cap(stroke, 0.3f);
 
        silhouette_create_shape_mesh(C, me, sil, stroke);
 
-       /* Rebuild mesh caches 
+       /* Rebuild mesh caches
         * TODO: Proper PBVH etc. */
        BKE_object_free_derived_caches(ob);
 }
 
 static void sculpt_silhouette_stroke_done(bContext *UNUSED(C), wmOperator *op)
 {
+#ifdef DEBUG_DRAW
        SilhouetteData *sil = op->customdata;
 
-#ifdef DEBUG_DRAW
        for (int i = 1; i < sil->current_stroke->totvert; i ++) {
                float v1[3], v2[3];
                copy_v3_v3(v1, &sil->current_stroke->points[i * 3 - 3]);
@@ -6733,15 +6734,29 @@ static void sculpt_silhouette_clean_draw(bContext *C, wmOperator *op)
 
 static int sculpt_silhouette_exec(bContext *C, wmOperator *op)
 {
+       int v_start, e_start, l_start, p_start;
        SilhouetteData *sil = op->customdata;
+       Object *ob = CTX_data_active_object(C);
+       Mesh *me = ob->data;
+
        if (!sil) {
                sil = silhouette_data_new(C);
                silhouette_set_ref_plane(sil);
                op->customdata = sil;
        }
 
-       sculpt_silhouette_calc_mesh(C, op);
-       sculpt_silhouette_stroke_done(C, op);
+       if (sil->current_stroke->totvert > 2) {
+               sculpt_undo_push_begin("draw Silhouette");
+               v_start = me->totvert;
+               e_start = me->totedge;
+               l_start = me->totloop;
+               p_start = me->totpoly;
+               sculpt_silhouette_calc_mesh(C, op);
+               sculpt_silhouette_stroke_done(C, op);
+
+               sculpt_undo_silhouette_push(ob, v_start, e_start, l_start, p_start);
+               sculpt_undo_push_end(C);
+       }
 
        return OPERATOR_FINISHED;
 }
@@ -6761,7 +6776,7 @@ static int sculpt_silhouette_modal(bContext *C, wmOperator *op, const wmEvent *e
                return OPERATOR_FINISHED;
        } else {
                if (sil->state == SIL_DRAWING) {
-                       sculpt_silhouette_stroke_update(C,mouse,op->customdata);
+                       sculpt_silhouette_stroke_update(mouse, op->customdata);
                }
                return OPERATOR_RUNNING_MODAL;
        }
@@ -6830,8 +6845,6 @@ static int sculpt_silhouette_poll(bContext *UNUSED(C))
 
 static void SCULPT_OT_silhouette_draw(wmOperatorType *ot)
 {
-       PropertyRNA *prop;
-
        /* identifiers */
        ot->name = "Draw Silhouette";
        ot->idname = "SCULPT_OT_silhouette_draw";
@@ -6845,7 +6858,7 @@ static void SCULPT_OT_silhouette_draw(wmOperatorType *ot)
        ot->cancel = sculpt_silhouette_stroke_done;
 
        /* flags */
-       ot->flag = OPTYPE_BLOCKING | OPTYPE_REGISTER | OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 /* end Silhouette */
 
index f1475b179c57d7fd615e95de829d192ecb07363e..bc08be5a8641100508087aeb35f40b4f2203e6b2 100644 (file)
@@ -70,6 +70,7 @@ typedef enum SculptUndoType {
        SCULPT_UNDO_DYNTOPO_BEGIN,
        SCULPT_UNDO_DYNTOPO_END,
        SCULPT_UNDO_DYNTOPO_SYMMETRIZE,
+       SCULPT_UNDO_SILHOUETTE
 } SculptUndoType;
 
 typedef struct SculptUndoNode {
@@ -99,6 +100,7 @@ typedef struct SculptUndoNode {
        BLI_bitmap **grid_hidden;
 
        /* bmesh */
+       /* Reused for Silhouette undonode. TODO: Maybe separate?*/
        struct BMLogEntry *bm_entry;
        bool applied;
        CustomData bm_enter_vdata;
@@ -116,6 +118,7 @@ typedef struct SculptUndoNode {
 
 SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType type);
 SculptUndoNode *sculpt_undo_get_node(PBVHNode *node);
+SculptUndoNode *sculpt_undo_silhouette_push(Object *ob, int v_start, int e_start, int l_start, int p_start);
 void sculpt_undo_push_begin(const char *name);
 void sculpt_undo_push_end(const struct bContext *C);
 
index 44bd872d107c9503b1e5c6ae7908d641cee4be14..676bf790f869453155292148eeaaa7a122416661 100644 (file)
@@ -68,6 +68,7 @@
 #include "bmesh.h"
 #include "paint_intern.h"
 #include "sculpt_intern.h"
+#include "BKE_object.h"
 
 /************************** Undo *************************/
 
@@ -446,6 +447,59 @@ static int sculpt_undo_bmesh_restore(bContext *C,
        return false;
 }
 
+static void sculpt_undo_silhouette_restore(bContext *C, Object *ob, SculptUndoNode *unode)
+{
+       Mesh *me = ob->data;
+       if(unode->applied){
+               unode->applied = false;
+
+               CustomData_free_elem(&me->vdata, me->totvert - unode->bm_enter_totvert, unode->bm_enter_totvert);
+               CustomData_free_elem(&me->edata, me->totedge - unode->bm_enter_totedge, unode->bm_enter_totedge);
+               CustomData_free_elem(&me->ldata, me->totloop - unode->bm_enter_totloop, unode->bm_enter_totloop);
+               CustomData_free_elem(&me->pdata, me->totpoly - unode->bm_enter_totpoly, unode->bm_enter_totpoly);
+
+               CustomData_realloc(&me->vdata, me->totvert - unode->bm_enter_totvert);
+               CustomData_realloc(&me->edata, me->totedge - unode->bm_enter_totedge);
+               CustomData_realloc(&me->ldata, me->totloop - unode->bm_enter_totloop);
+               CustomData_realloc(&me->pdata, me->totpoly - unode->bm_enter_totpoly);
+
+               BKE_mesh_update_customdata_pointers(me, true);
+
+               me->totvert = me->totvert - unode->bm_enter_totvert;
+               me->totedge = me->totedge - unode->bm_enter_totedge;
+               me->totloop = me->totloop - unode->bm_enter_totloop;
+               me->totpoly = me->totpoly - unode->bm_enter_totpoly;
+
+               BKE_object_free_derived_caches(ob);
+       } else {
+               unode->applied = true;
+               /* TODO: Add Redo
+                printf("Redo it!\n");
+
+               CustomData_realloc(&me->vdata, me->totvert + unode->bm_enter_totvert);
+               CustomData_realloc(&me->edata, me->totedge + unode->bm_enter_totedge);
+               CustomData_realloc(&me->ldata, me->totloop + unode->bm_enter_totloop);
+               CustomData_realloc(&me->pdata, me->totpoly + unode->bm_enter_totpoly);
+
+               CustomData_copy_data(&unode->bm_enter_vdata, &me->vdata, 0,
+                                               me->totvert, unode->bm_enter_totvert);
+               CustomData_copy_data(&unode->bm_enter_edata, &me->edata, 0,
+                                                        me->totedge, unode->bm_enter_totedge);
+               CustomData_copy_data(&unode->bm_enter_ldata, &me->ldata, 0,
+                                                        me->totloop, unode->bm_enter_totloop);
+               CustomData_copy_data(&unode->bm_enter_pdata, &me->pdata, 0,
+                                                        me->totpoly, unode->bm_enter_totpoly);
+
+               me->totvert += unode->bm_enter_totvert;
+               me->totloop += unode->bm_enter_totloop;
+               me->totpoly += unode->bm_enter_totpoly;
+               me->totedge += unode->bm_enter_totedge;
+
+               BKE_mesh_update_customdata_pointers(me, true);
+               BKE_object_free_derived_caches(ob);*/
+       }
+}
+
 static void sculpt_undo_restore(bContext *C, ListBase *lb)
 {
        Scene *scene = CTX_data_scene(C);
@@ -517,6 +571,12 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb)
                        case SCULPT_UNDO_DYNTOPO_SYMMETRIZE:
                                BLI_assert(!"Dynamic topology should've already been handled");
                                break;
+                       case SCULPT_UNDO_SILHOUETTE:
+                               sculpt_undo_silhouette_restore(C, ob, unode);
+                               rebuild = true;
+                               partial_update = false;
+                               return;
+                               break;
                }
        }
 
@@ -711,6 +771,8 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node,
                case SCULPT_UNDO_DYNTOPO_SYMMETRIZE:
                        BLI_assert(!"Dynamic topology should've already been handled");
                        break;
+               case SCULPT_UNDO_SILHOUETTE:
+                       break;
        }
        
        BLI_addtail(lb, unode);
@@ -868,6 +930,7 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob,
                        case SCULPT_UNDO_DYNTOPO_BEGIN:
                        case SCULPT_UNDO_DYNTOPO_END:
                        case SCULPT_UNDO_DYNTOPO_SYMMETRIZE:
+                       case SCULPT_UNDO_SILHOUETTE:
                                break;
                }
        }
@@ -875,6 +938,43 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob,
        return unode;
 }
 
+SculptUndoNode *sculpt_undo_silhouette_push(Object *ob, int v_start, int e_start, int l_start, int p_start)
+{
+       /* list is manipulated by multiple threads, so we lock */
+       BLI_lock_thread(LOCK_CUSTOM1);
+
+       ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_MESH);
+       SculptUndoNode *unode = lb->first;
+
+       if (!lb->first) {
+               unode = MEM_callocN(sizeof(*unode), __func__);
+
+               BLI_strncpy(unode->idname, ob->id.name, sizeof(unode->idname));
+               unode->type = SCULPT_UNDO_SILHOUETTE;
+               unode->applied = true;
+
+               Mesh *me = ob->data;
+
+               /* Store a copy of the silhouettes current vertices, loops, and
+                * polys. TODO: Add bridge edges and deleted existing geometry later */
+               /*TODO: Not a full copy is possible*/
+               CustomData_copy_data(&me->vdata, &unode->bm_enter_vdata, v_start, 0, me->totvert - v_start);
+               CustomData_copy_data(&me->edata, &unode->bm_enter_edata, e_start, 0, me->totedge - e_start);
+               CustomData_copy_data(&me->ldata, &unode->bm_enter_ldata, l_start, 0, me->totloop - l_start);
+               CustomData_copy_data(&me->pdata, &unode->bm_enter_pdata, p_start, 0, me->totpoly - p_start);
+               unode->bm_enter_totvert = me->totvert - v_start;
+               unode->bm_enter_totedge = me->totedge - e_start;
+               unode->bm_enter_totloop = me->totloop - l_start;
+               unode->bm_enter_totpoly = me->totpoly - p_start;
+
+               BLI_addtail(lb, unode);
+       }
+
+       BLI_unlock_thread(LOCK_CUSTOM1);
+       return unode;
+}
+
+
 SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node,
                                       SculptUndoType type)
 {
@@ -898,6 +998,10 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node,
        else if ((unode = sculpt_undo_get_node(node))) {
                BLI_unlock_thread(LOCK_CUSTOM1);
                return unode;
+       } else if (ELEM(type,SCULPT_UNDO_SILHOUETTE)) {
+               /* TODO:Remove? Should not reach. */
+               BLI_unlock_thread(LOCK_CUSTOM1);
+               return unode;
        }
 
        unode = sculpt_undo_alloc_node(ob, node, type);
@@ -935,6 +1039,8 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node,
                case SCULPT_UNDO_DYNTOPO_SYMMETRIZE:
                        BLI_assert(!"Dynamic topology should've already been handled");
                        break;
+               case SCULPT_UNDO_SILHOUETTE:/*TODO: Store data?*/
+                       break;
        }
 
        /* store active shape key */