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
path: root/source
diff options
context:
space:
mode:
authorRobert Wenzlaff <rwenzlaff@soylent-green.com>2003-10-20 00:52:34 +0400
committerRobert Wenzlaff <rwenzlaff@soylent-green.com>2003-10-20 00:52:34 +0400
commitd5322a6352edf8c6f23af18024c5c9ebc83b0c6f (patch)
treea97ac40d165f8e8de1d52b99f1f3036a66e1fa54 /source
parentde64d218a08548d5b33f412374f360585356a41c (diff)
Editmesh Undo:
User Info: Pressing UKey in mesh edit mode now undoes only last step. Undo can save upto 64 steps of undo info. This is configurable under User Prefs-> Edit Methods. The default is 32. High numbers of undo steps use a lot of memory, since each step stores a copy of the mesh. Shift-U redoes the last undone step (Undoes the undo.) Alt-U brings up a menu of possible steps that can be undone. Selecting an item on the list undoes that item plus all items before it on the list. The top selection "Undo All" is identical to the old Ukey. It undoes all editing since entering Editmode, even if all regular undo steps are used up. Undo info is only saved for one object at a time. You can leave and re- enter editmode for the same object, and all undo steps for that object are preserved. Undo info for an object is lost once a different object is edited. Coder Info: In order for undo to work, a checkpoint save has to be made. This is done with a call to undo_push_mesh("name of step"). This should be done after the last quick abort for a function (typ. the "if (G.obedit==0) return;", or similar). the undo_push_mesh() does alter some flags, so don't try to be too tricky and call undo_push_mesh() too late. The step name is what shows up in the undo_menu. The name "U" is reserved.
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_global.h21
-rw-r--r--source/blender/include/BIF_editmesh.h8
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h1
-rw-r--r--source/blender/src/buttons_editing.c5
-rw-r--r--source/blender/src/buttons_object.c3
-rw-r--r--source/blender/src/editmesh.c273
-rw-r--r--source/blender/src/editobject.c30
-rw-r--r--source/blender/src/space.c13
-rw-r--r--source/blender/src/usiblender.c5
9 files changed, 329 insertions, 30 deletions
diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h
index 2f75dd8be16..698982f5396 100644
--- a/source/blender/blenkernel/BKE_global.h
+++ b/source/blender/blenkernel/BKE_global.h
@@ -62,6 +62,17 @@ struct Object;
struct bSoundListener;
struct BMF_Font;
+#define UNDO_MAX 64
+#define UNDO_EDIT_MAX 64
+
+typedef struct UndoBufferEdit {
+
+ void *datablock;
+ char name[64];
+
+} UndoBufferEdit;
+
+
typedef struct Global {
/* active pointers */
@@ -143,7 +154,15 @@ typedef struct Global {
short special1, special2;
int flags;
-
+
+ /* editmode undo - written by intrr, ported by Det. Thorn */
+ struct UndoBufferEdit undo_edit[UNDO_EDIT_MAX+1];/* need one more for undoing first undo */
+ int undo_edit_level; /* index of last undo buffer created */
+ int undo_edit_highest; /* index of highest undo buffer in use */
+ void *undo_last_data; /* pointer to last datablock edited */
+ void (*undo_clear)(void); /* pointer to function to free the undo data */
+
+
} Global;
/* **************** GLOBAL ********************* */
diff --git a/source/blender/include/BIF_editmesh.h b/source/blender/include/BIF_editmesh.h
index 6cff0bdb692..f5103d70934 100644
--- a/source/blender/include/BIF_editmesh.h
+++ b/source/blender/include/BIF_editmesh.h
@@ -142,5 +142,13 @@ void sort_faces(void);
void vertices_to_sphere(void);
void fill_mesh(void);
+/* Editmesh Undo code */
+void undo_free_mesh(struct Mesh *me);
+void undo_push_mesh(char *name);
+void undo_pop_mesh(int steps);
+void undo_redo_mesh(void);
+void undo_clear_mesh(void);
+void undo_menu_mesh(void);
+
#endif
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 1c7bdc87d1a..da4799e48a1 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -119,6 +119,7 @@ typedef struct UserDef {
short menuthreshold1, menuthreshold2;
char fontname[64];
struct ListBase themes;
+ short undosteps, pad0[3];
} UserDef;
extern UserDef U; /* from usiblender.c !!!! */
diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c
index 2af018ce5b2..83611318cb4 100644
--- a/source/blender/src/buttons_editing.c
+++ b/source/blender/src/buttons_editing.c
@@ -1473,10 +1473,12 @@ void do_meshbuts(unsigned short event)
allqueue (REDRAWVIEW3D, 1);
break;
case B_ASSIGNVGROUP:
+ undo_push_mesh("Assign to vertex group");
assign_verts_defgroup ();
allqueue (REDRAWVIEW3D, 1);
break;
case B_REMOVEVGROUP:
+ undo_push_mesh("Remove from vertex group");
remove_verts_defgroup (0);
allqueue (REDRAWVIEW3D, 1);
break;
@@ -1577,11 +1579,13 @@ void do_meshbuts(unsigned short event)
G.f -= G_DISABLE_OK;
break;
case B_REMDOUB:
+ undo_push_mesh("Rem Doubles");
notice("Removed: %d", removedoublesflag(1, doublimit));
allqueue(REDRAWVIEW3D, 0);
break;
case B_SUBDIV:
waitcursor(1);
+ undo_push_mesh("Subdivide");
subdivideflag(1, 0.0, editbutflag & B_BEAUTY);
countall();
waitcursor(0);
@@ -1591,6 +1595,7 @@ void do_meshbuts(unsigned short event)
randfac= 10;
if(button(&randfac, 1, 100, "Rand fac:")==0) return;
waitcursor(1);
+ undo_push_mesh("Fractal Subdivide");
fac= -( (float)randfac )/100;
subdivideflag(1, fac, editbutflag & B_BEAUTY);
countall();
diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c
index e609d920afe..abb21181860 100644
--- a/source/blender/src/buttons_object.c
+++ b/source/blender/src/buttons_object.c
@@ -697,6 +697,7 @@ void do_common_editbuts(unsigned short event) // old name, is a mix of object an
case B_MATASS:
if(G.obedit && G.obedit->actcol>0) {
if(G.obedit->type == OB_MESH) {
+ undo_push_mesh("Assign material index");
evl= G.edvl.first;
while(evl) {
if( vlakselectedAND(evl, 1) )
@@ -823,6 +824,8 @@ void do_common_editbuts(unsigned short event) // old name, is a mix of object an
if(G.obedit) {
if(G.obedit->type == OB_MESH) {
evl= G.edvl.first;
+ if (event == B_SETSMOOTH) undo_push_mesh("Set Smooth");
+ else if (event==B_SETSOLID) undo_push_mesh("Set Solid");
while(evl) {
if( vlakselectedAND(evl, 1) ) {
if(event==B_SETSMOOTH) evl->flag |= ME_SMOOTH;
diff --git a/source/blender/src/editmesh.c b/source/blender/src/editmesh.c
index e390bfe463b..d85a5afd894 100644
--- a/source/blender/src/editmesh.c
+++ b/source/blender/src/editmesh.c
@@ -61,6 +61,7 @@
#include "DNA_view3d_types.h"
#include "DNA_material_types.h"
#include "DNA_texture_types.h"
+#include "DNA_userdef_types.h"
#include "BKE_utildefines.h"
#include "BKE_key.h"
@@ -102,6 +103,9 @@
static void free_editverts(ListBase *edve);
static float convex(float *v1, float *v2, float *v3, float *v4);
+/* EditMesh Undo */
+void make_editMesh_real(Mesh *me);
+void load_editMesh_real(Mesh *me);
/****/
@@ -170,7 +174,7 @@ struct HashEdge {
struct HashEdge *next;
};
-struct HashEdge *hashedgetab=0;
+struct HashEdge *hashedgetab=NULL;
/********* qsort routines *********/
@@ -935,6 +939,21 @@ static void free_editvert (EditVert *eve)
void make_editMesh(void)
{
Mesh *me;
+ int i;
+
+ me= get_mesh(G.obedit);
+ if (me != G.undo_last_data) {
+ G.undo_edit_level= -1;
+ G.undo_edit_highest= -1;
+ if (G.undo_clear) G.undo_clear();
+ G.undo_last_data= me;
+ G.undo_clear= undo_clear_mesh;
+ }
+ make_editMesh_real(me);
+}
+
+void make_editMesh_real(Mesh *me)
+{
MFace *mface;
TFace *tface;
MVert *mvert;
@@ -948,7 +967,6 @@ void make_editMesh(void)
/* because of reload */
free_editMesh();
- me= get_mesh(G.obedit);
G.totvert= tot= me->totvert;
if(tot==0) {
@@ -1167,9 +1185,20 @@ static void fix_faceindices(MFace *mface, EditVlak *evl, int nr)
/* load from EditMode to Mesh */
-void load_editMesh(void)
+void load_editMesh()
{
Mesh *me;
+
+ waitcursor(1);
+ countall();
+ me= get_mesh(G.obedit);
+
+ load_editMesh_real(me);
+}
+
+
+void load_editMesh_real(Mesh *me)
+{
MFace *mface;
MVert *mvert;
MSticky *ms;
@@ -1184,11 +1213,6 @@ void load_editMesh(void)
int usedDvert = 0;
#endif
- waitcursor(1);
- countall();
-
- me= get_mesh(G.obedit);
-
ototvert= me->totvert;
/* are there keys? */
@@ -1478,9 +1502,7 @@ void load_editMesh(void)
void remake_editMesh(void)
{
-
- if(okee("Reload Original data")==0) return;
-
+ undo_push_mesh("Undo all changes");
make_editMesh();
allqueue(REDRAWVIEW3D, 0);
makeDispList(G.obedit);
@@ -1651,6 +1673,8 @@ void convert_to_triface(int all)
{
EditVlak *evl, *evln, *next;
+ undo_push_mesh("Convert to triangles");
+
evl= G.edvl.first;
while(evl) {
next= evl->next;
@@ -1695,6 +1719,10 @@ void deselectall_mesh(void) /* toggle */
}
eve= eve->next;
}
+
+ if (a) undo_push_mesh("Deselect all");
+ else undo_push_mesh("Select all");
+
eve= G.edve.first;
while(eve) {
if(eve->h==0) {
@@ -1730,6 +1758,9 @@ void righthandfaces(int select) /* makes faces righthand turning */
/* in case (selected) faces were not done: start over with 'find the ultimate ...' */
waitcursor(1);
+
+ if (select==2) undo_push_mesh("Recalc normals inside");
+ if (select==1) undo_push_mesh("Recalc normals outside");
eed= G.eded.first;
while(eed) {
@@ -2331,6 +2362,7 @@ void edge_select(void)
if( (G.qual & LR_SHIFTKEY)==0) {
EditVert *eve;
+ undo_push_mesh("Edge select");
/* deselectall */
for(eve= G.edve.first; eve; eve= eve->next) eve->f&= ~1;
@@ -2367,6 +2399,7 @@ void mouse_mesh(void)
if(act) {
if((G.qual & LR_SHIFTKEY)==0) {
+ undo_push_mesh("Vertex select");
tekenvertices_special(0, act);
}
if( (act->f & 1)==0) act->f+= 1;
@@ -2387,6 +2420,8 @@ static void selectconnectedAll(void)
short flag=1,toggle=0;
if(G.eded.first==0) return;
+
+ undo_push_mesh("Select Connected (All)");
while(flag==1) {
flag= 0;
@@ -2441,7 +2476,8 @@ void selectconnected_mesh(void)
error(" Nothing indicated ");
return;
}
-
+
+ undo_push_mesh("Select linked");
/* clear test flags */
eve= G.edve.first;
while(eve) {
@@ -3001,6 +3037,8 @@ void xsortvert_flag(int flag)
}
if(aantal==0) return;
+ undo_push_mesh("Xsort");
+
/* allocate memory and sort */
sb= sortblock= (struct xvertsort *)MEM_mallocN(sizeof(struct xvertsort)*aantal,"sortremovedoub");
eve= G.edve.first;
@@ -3046,6 +3084,8 @@ void hashvert_flag(int flag)
eve= eve->next;
}
if(aantal==0) return;
+
+ undo_push_mesh("Hash");
/* allocate memory */
sb= sortblock= (struct xvertsort *)MEM_mallocN(sizeof(struct xvertsort)*aantal,"sortremovedoub");
@@ -3882,9 +3922,10 @@ void extrude_mesh(void)
TEST_EDITMESH
if(okee("Extrude")==0) return;
-
+
waitcursor(1);
-
+ undo_push_mesh("Extrude");
+
a= extrudeflag(1,1);
waitcursor(0);
if(a==0) {
@@ -3904,9 +3945,9 @@ void adduplicate_mesh(void)
TEST_EDITMESH
waitcursor(1);
+ undo_push_mesh("Duplicate");
adduplicateflag(1);
waitcursor(0);
-
countall(); /* for G.totvert in calc_meshverts() */
transform('d');
}
@@ -3919,7 +3960,7 @@ void split_mesh(void)
if(okee(" Split ")==0) return;
waitcursor(1);
-
+ undo_push_mesh("Split");
/* make duplicate first */
adduplicateflag(1);
/* old faces have 3x flag 128 set, delete them */
@@ -3937,8 +3978,11 @@ void separatemenu(void)
{
short event;
- event = pupmenu("Separate %t|Selected%x1|All loose parts%x2");
-
+ event = pupmenu("Separate (No undo!) %t|Selected%x1|All loose parts%x2");
+
+ if (event==0) return;
+ waitcursor(1);
+
switch (event) {
case 1:
@@ -3948,6 +3992,7 @@ void separatemenu(void)
separate_mesh_loose();
break;
}
+ waitcursor(0);
}
@@ -4290,6 +4335,8 @@ void extrude_repeat_mesh(int steps, float offs)
TEST_EDITMESH
waitcursor(1);
+
+ undo_push_mesh("Extrude Repeat");
/* dvec */
dvec[0]= G.vd->persinv[2][0];
@@ -4331,6 +4378,8 @@ void spin_mesh(int steps,int degr,float *dvec, int mode)
TEST_EDITMESH
waitcursor(1);
+
+ undo_push_mesh("Spin");
/* imat and centre and size */
Mat3CpyMat4(bmat, G.obedit->obmat);
@@ -4417,7 +4466,9 @@ void screw_mesh(int steps,int turns)
error("Only in frontview!");
return;
}
-
+
+ undo_push_mesh("Screw");
+
/* clear flags */
eve= G.edve.first;
while(eve) {
@@ -4668,11 +4719,13 @@ void delete_mesh(void)
if(event<1) return;
if(event==10 ) {
+ undo_push_mesh("Erase Vertices");
erase_edges(&G.eded);
erase_faces(&G.edvl);
erase_vertices(&G.edve);
}
else if(event==4) {
+ undo_push_mesh("Erase Edges & Faces");
evl= G.edvl.first;
while(evl) {
nextvl= evl->next;
@@ -4714,6 +4767,7 @@ void delete_mesh(void)
}
}
else if(event==1) {
+ undo_push_mesh("Erase Edges");
eed= G.eded.first;
while(eed) {
nexted= eed->next;
@@ -4757,14 +4811,19 @@ void delete_mesh(void)
}
}
- else if(event==2) delvlakflag(1);
+ else if(event==2) {
+ undo_push_mesh("Erase Faces");
+ delvlakflag(1);
+ }
else if(event==3) {
+ undo_push_mesh("Erase All");
// if(G.edve.first) BLI_freelist(&G.edve);
if(G.edve.first) free_editverts(&G.edve);
if(G.eded.first) BLI_freelist(&G.eded);
if(G.edvl.first) freevlaklist(&G.edvl);
}
else if(event==5) {
+ undo_push_mesh("Erase Only Faces");
evl= G.edvl.first;
while(evl) {
nextvl= evl->next;
@@ -5175,6 +5234,8 @@ void vertexsmooth(void)
eve= eve->next;
}
if(teller==0) return;
+
+ undo_push_mesh("Smooth");
adr=adror= (float *)MEM_callocN(3*sizeof(float *)*teller, "vertsmooth");
eve= G.edve.first;
@@ -5237,7 +5298,9 @@ void vertexnoise(void)
float b2, ofs, vec[3];
if(G.obedit==0) return;
-
+
+ undo_push_mesh("Noise");
+
ma= give_current_material(G.obedit, G.obedit->actcol);
if(ma==0 || ma->mtex[0]==0 || ma->mtex[0]->tex==0) {
return;
@@ -5609,6 +5672,8 @@ void join_triangles(void)
totedge = count_edges(G.eded.first);
if(totedge==0) return;
+ undo_push_mesh("Join triangles");
+
evlar= (EVPTuple *) MEM_callocN(totedge * sizeof(EVPTuple), "jointris");
ok = collect_quadedges(evlar, G.eded.first, G.edvl.first);
@@ -5702,6 +5767,8 @@ void edge_flip(void)
totedge = count_edges(G.eded.first);
if(totedge==0) return;
+ undo_push_mesh("Flip edges");
+
/* temporary array for : edge -> face[1], face[2] */
evlar= (EVPTuple *) MEM_callocN(totedge * sizeof(EVPTuple), "edgeflip");
@@ -5808,6 +5875,8 @@ void beauty_fill(void)
if(totedge==0) return;
if(okee("Beauty Fill")==0) return;
+
+ undo_push_mesh("Beauty Fill");
/* temp block with face pointers */
evlar= (EVPTuple *) MEM_callocN(totedge * sizeof(EVPTuple), "beautyfill");
@@ -6360,6 +6429,9 @@ void vertices_to_sphere(void)
TEST_EDITMESH
if(button(&perc, 1, 100, "Percentage:")==0) return;
+
+ undo_push_mesh("To Sphere");
+
fac= perc/100.0;
facm= 1.0-fac;
@@ -6421,6 +6493,8 @@ void fill_mesh(void)
waitcursor(1);
+ undo_push_mesh("Fill");
+
/* copy all selected vertices */
eve= G.edve.first;
while(eve) {
@@ -6998,7 +7072,9 @@ void KnifeSubdivide(char mode){
if (G.obedit==0) return;
- /* Set a knife cursor here ??? */
+ undo_push_mesh("Knife");
+
+ /* Set a knife cursor here */
oldcursor=get_cursor();
set_cursor(CURSOR_PENCIL);
@@ -7150,3 +7226,156 @@ short seg_intersect(EditEdge *e, CutCurve *c, int len){
return(isect);
}
+
+/*********************** EDITMESH UNDO ********************************/
+/* Mesh Edit undo by Alexander Ewring, */
+/* ported by Robert Wenzlaff */
+/* */
+/* Any meshedit function wishing to create an undo step, calls */
+/* undo_push_mesh("menu_name_of_step"); */
+
+Mesh *undo_new_mesh(void)
+{
+ return(MEM_callocN(sizeof(Mesh), "undo_mesh"));
+}
+
+void undo_free_mesh(Mesh *me)
+{
+ if(me->mat) MEM_freeN(me->mat);
+ if(me->orco) MEM_freeN(me->orco);
+ if(me->mface) MEM_freeN(me->mface);
+ if(me->tface) MEM_freeN(me->tface);
+ if(me->mvert) MEM_freeN(me->mvert);
+ if(me->dvert) free_dverts(me->dvert, me->totvert);
+ if(me->mcol) MEM_freeN(me->mcol);
+ if(me->msticky) MEM_freeN(me->msticky);
+ if(me->bb) MEM_freeN(me->bb);
+ if(me->disp.first) freedisplist(&me->disp);
+ MEM_freeN(me);
+}
+
+
+void undo_push_mesh(char *name)
+{
+ Mesh *me;
+ int i;
+
+ countall();
+
+ G.undo_edit_level++;
+
+ if (G.undo_edit_level<0) {
+ printf("undo: ERROR: G.undo_edit_level negative\n");
+ return;
+ }
+
+
+ if (G.undo_edit[G.undo_edit_level].datablock != 0) {
+ undo_free_mesh(G.undo_edit[G.undo_edit_level].datablock);
+ }
+ if (strcmp(name, "U")!=0) {
+ for (i=G.undo_edit_level+1; i<(U.undosteps-1); i++) {
+ if (G.undo_edit[i].datablock != 0) {
+ undo_free_mesh(G.undo_edit[i].datablock);
+ G.undo_edit[i].datablock= 0;
+ }
+ }
+ G.undo_edit_highest= G.undo_edit_level;
+ }
+
+ me= undo_new_mesh();
+
+ if (G.undo_edit_level>=U.undosteps) {
+ G.undo_edit_level--;
+ undo_free_mesh((Mesh*)G.undo_edit[0].datablock);
+ G.undo_edit[0].datablock= 0;
+ for (i=0; i<(U.undosteps-1); i++) {
+ G.undo_edit[i]= G.undo_edit[i+1];
+ }
+ }
+
+ if (strcmp(name, "U")!=0) strcpy(G.undo_edit[G.undo_edit_level].name, name);
+ //printf("undo: saving block: %d [%s]\n", G.undo_edit_level, G.undo_edit[G.undo_edit_level].name);
+
+ G.undo_edit[G.undo_edit_level].datablock= (void*)me;
+ load_editMesh_real(me);
+}
+
+void undo_pop_mesh(int steps) /* steps == 1 is one step */
+{
+ if (G.undo_edit_level > (steps-2)) {
+ undo_push_mesh("U");
+ G.undo_edit_level-= steps;
+//printf("undo: restoring block: %d [%s]\n", G.undo_edit_level, G.undo_edit[G.undo_edit_level].name); -
+ make_editMesh_real((Mesh*)G.undo_edit[G.undo_edit_level].datablock);
+ allqueue(REDRAWVIEW3D, 0);
+ makeDispList(G.obedit);
+ G.undo_edit_level--;
+ } else error("Can't undo");
+}
+
+
+void undo_redo_mesh(void)
+{
+ if ( (G.undo_edit[G.undo_edit_level+2].datablock) &&
+ ( (G.undo_edit_level+1) <= G.undo_edit_highest ) ) {
+ G.undo_edit_level++;
+ //printf("redo: restoring block: %d [%s]\n", G.undo_edit_level+1, G.undo_edit[G.undo_edit_level+1].name);-
+ make_editMesh_real((Mesh*)G.undo_edit[G.undo_edit_level+1].datablock);
+ allqueue(REDRAWVIEW3D, 0);
+ makeDispList(G.obedit);
+ } else error("Can't redo");
+}
+
+void undo_clear_mesh(void)
+{
+ int i;
+ Mesh *me;
+
+ for (i=0; i<=UNDO_EDIT_MAX; i++) {
+ me= (Mesh*) G.undo_edit[i].datablock;
+ if (me) {
+ //printf("undo: freeing %d\n", i);
+ undo_free_mesh(me);
+ G.undo_edit[i].datablock= 0;
+ }
+ }
+}
+
+void undo_menu_mesh(void)
+{
+ short event=66;
+ int i, lasti;
+ char menu[2080];
+
+ TEST_EDITMESH
+
+ lasti= (G.undo_edit_level>30) ? G.undo_edit_level-30 : 0;
+
+ strcpy(menu, "UNDO %t");
+ strcat(menu, "|%l|All changes%x1|%l");
+
+ for (i=G.undo_edit_level; i>=lasti; i--) {
+ sprintf(menu+strlen(menu), "|%s%%x%d", G.undo_edit[i].name, i+2);
+ }
+
+ if (lasti) strcat(menu, "|%l|More...%x33|%l");
+
+ event= pupmenu(menu);
+
+ if (event==33){ /* More options.*/
+ strcpy(menu, "UNDO %t");
+ strcat(menu, "|%l|All changes%x1|%l");
+
+ for (i=lasti; i>=0; i--) {
+ sprintf(menu+strlen(menu), "|%s%%x%d", G.undo_edit[i].name, i+2);
+ }
+ event= pupmenu(menu);
+ }
+
+ if(event<1) return;
+
+ if (event==1) remake_editMesh();
+ else undo_pop_mesh(G.undo_edit_level-event+3);
+}
+
diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c
index 7604e6d4d9c..0e12094a845 100644
--- a/source/blender/src/editobject.c
+++ b/source/blender/src/editobject.c
@@ -1500,21 +1500,25 @@ void special_editmenu(void)
switch(nr) {
case 1:
+ undo_push_mesh("Subdivide");
subdivideflag(1, 0.0, editbutflag);
break;
case 2:
randfac= 10;
if(button(&randfac, 1, 100, "Rand fac:")==0) return;
fac= -( (float)randfac )/100;
+ undo_push_mesh("Subdivide Fractal");
subdivideflag(1, fac, editbutflag);
break;
case 3:
+ undo_push_mesh("Subdivide Smooth");
subdivideflag(1, 0.0, editbutflag | B_SMOOTH);
break;
case 4:
mergemenu();
break;
case 5:
+ undo_push_mesh("Rem Doubles");
notice("Removed: %d", removedoublesflag(1, doublimit));
break;
case 6:
@@ -1553,9 +1557,6 @@ void special_editmenu(void)
}
}
-
-
-
countall();
allqueue(REDRAWVIEW3D, 0);
@@ -3743,6 +3744,24 @@ void view_editmove(unsigned char event)
break;
}
}
+
+char *transform_mode_to_string(int mode)
+{
+ switch(mode) {
+ case 'g': return("Grab"); break;
+ case 's': return("Scale"); break;
+ case 'r': return("Rotate"); break;
+ case 'G': return("Grab proportional"); break;
+ case 'C': return("Scale proportional"); break;
+ case 'R': return("Rotate proportional"); break;
+ case 'S': return("Shear"); break;
+ case 'N': return("Shrink/Fatten"); break;
+ case 'w': return("Warp"); break;
+ case 'd': return("Duplicate"); break;
+ default: return("Transform");
+ }
+}
+
void transform(int mode) /* 'g' 'G' 'r' 'R' 's' 'S' 't' or 'w' 'N' */
{
short canceled = 0;
@@ -3780,6 +3799,10 @@ void transform(int mode) /* 'g' 'G' 'r' 'R' 's' 'S' 't' or 'w' 'N' */
}
if(mode=='w' && G.obedit==0) return;
+ if (G.obedit && G.obedit->type == OB_MESH) {
+ undo_push_mesh(transform_mode_to_string(mode));
+ }
+
/* what data will be involved? */
if(G.obedit) {
if(mode=='N') vertexnormals(0);
@@ -4734,6 +4757,7 @@ void transform(int mode) /* 'g' 'G' 'r' 'R' 's' 'S' 't' or 'w' 'N' */
if(event==ESCKEY || event==RIGHTMOUSE) {
canceled=1;
+ G.undo_edit_level--;
tv= transvmain;
tob= transmain;
for(a=0; a<tottrans; a++, tob++, tv++) {
diff --git a/source/blender/src/space.c b/source/blender/src/space.c
index 7877a7c3423..898d8fd5b29 100644
--- a/source/blender/src/space.c
+++ b/source/blender/src/space.c
@@ -1168,7 +1168,11 @@ void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
break;
case UKEY:
if(G.obedit) {
- if(G.obedit->type==OB_MESH) remake_editMesh();
+ if(G.obedit->type==OB_MESH){
+ if (G.qual & LR_ALTKEY) undo_menu_mesh();
+ else if (G.qual & LR_SHIFTKEY) undo_redo_mesh();
+ else undo_pop_mesh(1);
+ }
else if(G.obedit->type==OB_ARMATURE) remake_editArmature();
else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) remake_editNurb();
else if(G.obedit->type==OB_LATTICE) remake_editLatt();
@@ -1881,7 +1885,9 @@ void drawinfospace(ScrArea *sa, void *spacedata)
uiBlockSetCol(block, BUTGREY);
-
+ uiDefButS(block, NUMSLI, B_DRAWINFO, "UndoSteps:",
+ (xpos+edgespace+2*smallprefbut+8),y2,(medprefbut+2),buth,
+ &(U.undosteps), 1, 64, 0, 0, "Number of undo steps avail. in Editmode. Smaller conserves memory.");
uiDefBut(block, LABEL,0,"Auto keyframe on:",
(xpos+edgespace+(2*medprefbut)+midspace),y3label,medprefbut,buth,
@@ -1935,8 +1941,7 @@ void drawinfospace(ScrArea *sa, void *spacedata)
uiDefButS(block, TOG|BIT|6, 0, "Ipo",
(xpos+edgespace+(8*midspace)+(3*medprefbut)+(5*smallprefbut)),y1,smallprefbut,buth,
&(U.dupflag), 0, 0, 0, 0, "Causes ipo data to be duplicated with Shift+D");
-
-
+
} else if(U.userpref == 2) { /* language & colors */
#ifdef INTERNATIONAL
diff --git a/source/blender/src/usiblender.c b/source/blender/src/usiblender.c
index 00dd129084c..11283f26d0f 100644
--- a/source/blender/src/usiblender.c
+++ b/source/blender/src/usiblender.c
@@ -65,6 +65,7 @@
#include "DNA_object_types.h"
#include "DNA_space_types.h"
#include "DNA_userdef_types.h"
+#include "DNA_mesh_types.h"
#include "BKE_blender.h"
#include "BKE_curve.h"
@@ -225,6 +226,8 @@ int BIF_read_homefile(void)
U.mixbufsize= 2048;
}
space_set_commmandline_options();
+
+ if (U.undosteps==0) U.undosteps=32;
reset_autosave();
}
@@ -564,6 +567,8 @@ void exit_usiblender(void)
mainwindow_close();
}
+ if (G.undo_clear) G.undo_clear();
+
BLI_freelistN(&U.themes);
if(totblock!=0) {