Add undo/redo support for paint masks.
authorNicholas Bishop <nicholasbishop@gmail.com>
Thu, 10 May 2012 20:34:47 +0000 (20:34 +0000)
committerNicholas Bishop <nicholasbishop@gmail.com>
Thu, 10 May 2012 20:34:47 +0000 (20:34 +0000)
source/blender/blenkernel/BKE_paint.h
source/blender/editors/sculpt_paint/sculpt_intern.h
source/blender/editors/sculpt_paint/sculpt_undo.c

index 7bee131c63b83b10a2f644eb111540957fc604e0..bfefd9dc3b89603deca818e081861c6b2afe130e 100644 (file)
@@ -84,6 +84,7 @@ typedef struct SculptSession {
        int totvert, totpoly;
        float *face_normals;
        struct KeyBlock *kb;
+       float *vmask;
        
        /* Mesh connectivity */
        const struct MeshElemMap *pmap;
index 8ccf55ec4fba55ac3d319bb2aa4390617b4be21b..14fb122578a9da9944855af760ec721fbd7104ef 100644 (file)
@@ -69,7 +69,8 @@ int sculpt_stroke_get_location(bContext *C, float out[3], float mouse[2]);
 
 typedef enum {
        SCULPT_UNDO_COORDS,
-       SCULPT_UNDO_HIDDEN
+       SCULPT_UNDO_HIDDEN,
+       SCULPT_UNDO_MASK
 } SculptUndoType;
 
 typedef struct SculptUndoNode {
@@ -83,6 +84,7 @@ typedef struct SculptUndoNode {
        float (*co)[3];
        float (*orig_co)[3];
        short (*no)[3];
+       float *mask;
        int totvert;
 
        /* non-multires */
index ea5c173e41099ec9badef570124c2c8782ddd848..1ab93f1ce7b3dcd7128bfc684424a1a5a0ceed00 100644 (file)
@@ -217,6 +217,49 @@ static int sculpt_undo_restore_hidden(bContext *C, DerivedMesh *dm,
        return 1;
 }
 
+static int sculpt_undo_restore_mask(bContext *C, DerivedMesh *dm, SculptUndoNode *unode)
+{
+       Object *ob= CTX_data_active_object(C);
+       SculptSession *ss= ob->sculpt;
+       MVert *mvert;
+       float *vmask;
+       int *index, i, j;       
+       
+       if(unode->maxvert) {
+               /* regular mesh restore */
+
+               index= unode->index;
+               mvert= ss->mvert;
+               vmask= ss->vmask;
+
+               for(i=0; i<unode->totvert; i++) {
+                       SWAP(float, vmask[index[i]], unode->mask[i]);
+                       mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE;
+               }
+       }
+       else if(unode->maxgrid && dm->getGridData) {
+               /* multires restore */
+               CCGElem **grids, *grid;
+               CCGKey key;
+               float *mask;
+               int gridsize;
+
+               grids= dm->getGridData(dm);
+               gridsize= dm->getGridSize(dm);
+               dm->getGridKey(dm, &key);
+
+               mask = unode->mask;
+               for(j=0; j<unode->totgrid; j++) {
+                       grid= grids[unode->grids[j]];
+
+                       for(i=0; i<gridsize*gridsize; i++, mask++)
+                               SWAP(float, *CCG_elem_offset_mask(&key, grid, i), *mask);
+               }
+       }
+
+       return 1;
+}
+
 static void sculpt_undo_restore(bContext *C, ListBase *lb)
 {
        Scene *scene = CTX_data_scene(C);
@@ -251,14 +294,18 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb)
                        continue;
                }
 
-               switch (unode->type) {
+               switch(unode->type) {
                        case SCULPT_UNDO_COORDS:
                                if (sculpt_undo_restore_coords(C, dm, unode))
-                                       update = 1;
+                                       update= 1;
                                break;
                        case SCULPT_UNDO_HIDDEN:
                                if (sculpt_undo_restore_hidden(C, dm, unode))
-                                       rebuild = 1;
+                                       rebuild= 1;
+                               break;
+                       case SCULPT_UNDO_MASK:
+                               if(sculpt_undo_restore_mask(C, dm, unode))
+                                       update= 1;
                                break;
                }
        }
@@ -324,6 +371,8 @@ static void sculpt_undo_free(ListBase *lb)
                        }
                        MEM_freeN(unode->grid_hidden);
                }
+               if(unode->mask)
+                       MEM_freeN(unode->mask);
        }
 }
 
@@ -403,6 +452,10 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node,
                                unode->vert_hidden = BLI_BITMAP_NEW(allvert, "SculptUndoNode.vert_hidden");
                
                        break;
+               case SCULPT_UNDO_MASK:
+                       unode->mask= MEM_mapallocN(sizeof(float)*allvert, "SculptUndoNode.mask");
+                       undo_paint_push_count_alloc(UNDO_PAINT_MESH, (sizeof(float) * sizeof(int))*allvert);
+                       break;
        }
        
        BLI_addtail(lb, unode);
@@ -464,6 +517,17 @@ static void sculpt_undo_store_hidden(Object *ob, SculptUndoNode *unode)
        }
 }
 
+static void sculpt_undo_store_mask(Object *ob, SculptUndoNode *unode)
+{
+       SculptSession *ss = ob->sculpt;
+       PBVHVertexIter vd;
+
+       BLI_pbvh_vertex_iter_begin(ss->pbvh, unode->node, vd, PBVH_ITER_ALL) {
+               unode->mask[vd.i] = *vd.mask;
+       }
+       BLI_pbvh_vertex_iter_end;
+}
+
 SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node,
                                       SculptUndoType type)
 {
@@ -504,6 +568,9 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node,
                case SCULPT_UNDO_HIDDEN:
                        sculpt_undo_store_hidden(ob, unode);
                        break;
+               case SCULPT_UNDO_MASK:
+                       sculpt_undo_store_mask(ob, unode);
+                       break;
        }
 
        /* store active shape key */