Changed the sculptmode undo system slightly to make it easier to improve/extend. Should be helpful in integrating multires into the undo system better.

This commit is contained in:
Nicholas Bishop 2006-11-21 04:03:39 +00:00
parent 2d0a83ba09
commit ba32e1e2fa
2 changed files with 88 additions and 50 deletions

@ -34,6 +34,7 @@ struct uiBlock;
struct BrushData;
struct Mesh;
struct Object;
struct PartialVisibility;
struct Scene;
struct ScrArea;
@ -57,7 +58,12 @@ void sculptmode_init(struct Scene *);
void sculptmode_free_all(struct Scene *);
/* Undo */
void sculptmode_undo_push(char *str, int verts, int pmv, int fe);
typedef enum SculptUndoType {
SUNDO_VERT= 1, /* Vertex locations modified */
SUNDO_TOPO= 2, /* Any face/edge change, different # of verts, etc. */
SUNDO_PVIS= 4 /* Mesh.pv changed */
} SculptUndoType;
void sculptmode_undo_push(char *str, SculptUndoType type);
void sculptmode_undo();
void sculptmode_redo();
void sculptmode_undo_menu();
@ -79,6 +85,8 @@ void set_sculpt_object(struct Object *ob);
void set_sculptmode();
/* Partial Mesh Visibility */
struct PartialVisibility *sculptmode_copy_pmv(struct PartialVisibility *);
void sculptmode_pmv_free(struct PartialVisibility *);
void sculptmode_revert_pmv(struct Mesh *me);
void sculptmode_pmv_off(struct Mesh *me);
void sculptmode_pmv(int mode);

@ -198,6 +198,8 @@ void sculptmode_free_vertexusers(struct Scene *sce)
typedef struct SculptUndoStep {
struct SculptUndoStep *next, *prev;
SculptUndoType type;
char *str;
MVert *verts;
@ -206,7 +208,6 @@ typedef struct SculptUndoStep {
MFace *faces;
int totvert, totedge, totface;
int pv_stored;
PartialVisibility *pv;
} SculptUndoStep;
typedef struct SculptUndo {
@ -214,10 +215,39 @@ typedef struct SculptUndo {
SculptUndoStep *cur;
} SculptUndo;
void sculptmode_undo_debug_print_type(SculptUndoType t)
{
if(t & SUNDO_VERT) printf("VERT,");
if(t & SUNDO_TOPO) printf("TOPO,");
if(t & SUNDO_PVIS) printf("PVIS,");
}
void sculptmode_undo_push_debug_print()
{
SculptUndo *su= G.scene->sculptdata.undo;
if(su) {
int i;
SculptUndoStep *sus;
for(i=1, sus= su->steps.first; sus; ++i, sus= sus->next) {
printf("%d(%p): ",i,sus);
if(sus == su->cur) printf("A");
else printf("-");
printf(" type(");
sculptmode_undo_debug_print_type(sus->type);
printf(") v(%p) f/e/vc/fc/ec(%p,%p,%d,%d,%d) pv(%p) name(%s)\n",sus->verts,sus->faces,sus->edges,sus->totvert,sus->totface,sus->totedge,sus->pv,sus->str);
}
}
else
printf("No undo data");
printf("\n");
}
void sculptmode_undo_init()
{
G.scene->sculptdata.undo= MEM_callocN(sizeof(SculptUndo), "Sculpt Undo");
sculptmode_undo_push("Original", 1, 1, 1);
sculptmode_undo_push("Original", SUNDO_VERT|SUNDO_TOPO|SUNDO_PVIS);
}
void sculptmode_undo_free_link(SculptUndoStep *sus)
@ -228,21 +258,16 @@ void sculptmode_undo_free_link(SculptUndoStep *sus)
MEM_freeN(sus->edges);
if(sus->faces)
MEM_freeN(sus->faces);
if(sus->pv) {
MEM_freeN(sus->pv->vert_map);
MEM_freeN(sus->pv->edge_map);
MEM_freeN(sus->pv->old_faces);
MEM_freeN(sus->pv->old_edges);
MEM_freeN(sus->pv);
}
if(sus->pv)
sculptmode_pmv_free(sus->pv);
}
void sculptmode_undo_pull_chopped(SculptUndoStep *sus)
{
SculptUndoStep *f;
for(f= sus; f && !(sus->edges || sus->faces); f= f->prev)
if(f->edges || f->faces) {
for(f= sus; f && !(sus->type & SUNDO_TOPO); f= f->prev)
if(f->type & SUNDO_TOPO) {
sus->edges= f->edges;
f->edges= NULL;
sus->faces= f->faces;
@ -250,14 +275,15 @@ void sculptmode_undo_pull_chopped(SculptUndoStep *sus)
sus->totvert= f->totvert;
sus->totedge= f->totedge;
sus->totface= f->totface;
sus->type |= SUNDO_TOPO;
break;
}
for(f= sus; f && !sus->pv_stored; f= f->prev)
if(f->pv_stored) {
for(f= sus; f && !(sus->type & SUNDO_PVIS); f= f->prev)
if(f->type & SUNDO_PVIS) {
sus->pv= f->pv;
f->pv= NULL;
sus->pv_stored= 1;
sus->type |= SUNDO_PVIS;
break;
}
}
@ -272,8 +298,7 @@ void sculptmode_undo_free(Scene *sce)
MEM_freeN(sce->sculptdata.undo);
}
PartialVisibility *sculptmode_copy_pmv(PartialVisibility *);
void sculptmode_undo_push(char *str, int verts, int fe, int pv)
void sculptmode_undo_push(char *str, SculptUndoType type)
{
int cnt= 7;
SculptUndo *su= G.scene->sculptdata.undo;
@ -288,18 +313,18 @@ void sculptmode_undo_push(char *str, int verts, int fe, int pv)
}
/* Initialize undo data */
n->type= type;
n->str= str;
if(verts)
if(type & SUNDO_VERT)
n->verts= MEM_dupallocN(me->mvert);
if(fe) {
if(type & SUNDO_TOPO) {
n->edges= MEM_dupallocN(me->medge);
n->faces= MEM_dupallocN(me->mface);
n->totvert= me->totvert;
n->totedge= me->totedge;
n->totface= me->totface;
}
if(pv) {
n->pv_stored= 1;
if(type & SUNDO_PVIS) {
if(me->pv)
n->pv= sculptmode_copy_pmv(me->pv);
}
@ -329,7 +354,8 @@ void sculptmode_undo_update(SculptUndoStep *newcur)
Mesh *me= get_mesh(sd->active_ob);
SculptUndoStep *oldcur= sd->undo->cur, *sus;
Object *ob= sd->active_ob;
int forward= 0, do_fe, do_pv;
int forward= 0;
SculptUndoType type= SUNDO_VERT;
/* No update if undo step hasn't changed */
if(newcur == oldcur) return;
@ -347,24 +373,23 @@ void sculptmode_undo_update(SculptUndoStep *newcur)
}
/* Check if faces/edges have been modified between oldcur and newcur */
do_fe= 0;
for(sus= forward?oldcur->next:newcur->next;
sus && sus != (forward?newcur->next:oldcur->next); sus= sus->next)
if(sus->edges || sus->faces) {
do_fe= 1;
if(sus->type & SUNDO_TOPO) {
type |= SUNDO_TOPO;
break;
}
do_pv= 0;
for(sus= forward?oldcur->next:newcur->next;
sus && sus != (forward?newcur->next:oldcur->next); sus= sus->next)
if(sus->pv_stored) {
do_pv= 1;
if(sus->type & SUNDO_PVIS) {
type |= SUNDO_PVIS;
break;
}
if(do_fe)
if(type & SUNDO_TOPO)
for(sus= newcur; sus; sus= sus->prev) {
if(sus->edges || sus->faces) {
if(sus->type & SUNDO_TOPO) {
CustomData_free_layer(&me->edata, CD_MEDGE, me->totedge);
CustomData_free_layer(&me->fdata, CD_MFACE, me->totface);
@ -380,21 +405,17 @@ void sculptmode_undo_update(SculptUndoStep *newcur)
}
}
if(do_pv)
if(type & SUNDO_PVIS)
for(sus= newcur; sus; sus= sus->prev)
if(sus->pv_stored) {
if(me->pv) {
MEM_freeN(me->pv->vert_map);
MEM_freeN(me->pv->edge_map);
MEM_freeN(me->pv->old_faces);
MEM_freeN(me->pv->old_edges);
MEM_freeN(me->pv);
}
if(sus->type & SUNDO_PVIS) {
if(me->pv)
sculptmode_pmv_free(me->pv);
me->pv= NULL;
if(newcur->pv)
me->pv= sculptmode_copy_pmv(newcur->pv);
if(sus->pv)
me->pv= sculptmode_copy_pmv(sus->pv);
break;
}
sd->undo->cur= newcur;
set_sculpt_object(ob);
@ -1656,19 +1677,19 @@ void sculpt()
switch(G.scene->sculptdata.brush_type) {
case DRAW_BRUSH:
sculptmode_undo_push("Draw Brush", 1,0,0); break;
sculptmode_undo_push("Draw Brush", SUNDO_VERT); break;
case SMOOTH_BRUSH:
sculptmode_undo_push("Smooth Brush", 1,0,0); break;
sculptmode_undo_push("Smooth Brush", SUNDO_VERT); break;
case PINCH_BRUSH:
sculptmode_undo_push("Pinch Brush", 1,0,0); break;
sculptmode_undo_push("Pinch Brush", SUNDO_VERT); break;
case INFLATE_BRUSH:
sculptmode_undo_push("Inflate Brush", 1,0,0); break;
sculptmode_undo_push("Inflate Brush", SUNDO_VERT); break;
case GRAB_BRUSH:
sculptmode_undo_push("Grab Brush", 1,0,0); break;
sculptmode_undo_push("Grab Brush", SUNDO_VERT); break;
case LAYER_BRUSH:
sculptmode_undo_push("Layer Brush", 1,0,0); break;
sculptmode_undo_push("Layer Brush", SUNDO_VERT); break;
default:
sculptmode_undo_push("Sculpting", 1,0,0); break;
sculptmode_undo_push("Sculpting", SUNDO_VERT); break;
}
if(G.vd->depths) G.vd->depths->damaged= 1;
@ -1718,6 +1739,15 @@ PartialVisibility *sculptmode_copy_pmv(PartialVisibility *pmv)
return n;
}
void sculptmode_pmv_free(PartialVisibility *pv)
{
MEM_freeN(pv->vert_map);
MEM_freeN(pv->edge_map);
MEM_freeN(pv->old_faces);
MEM_freeN(pv->old_edges);
MEM_freeN(pv);
}
void sculptmode_revert_pmv(Mesh *me)
{
if(me->pv) {
@ -1984,7 +2014,7 @@ void sculptmode_pmv(int mode)
scrarea_do_windraw(curarea);
sculptmode_undo_push("Partial mesh hide", 1, 1, 1);
sculptmode_undo_push("Partial mesh hide", SUNDO_VERT|SUNDO_TOPO|SUNDO_PVIS);
waitcursor(0);
}