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.
This commit is contained in:
@@ -62,6 +62,17 @@ struct Object;
|
|||||||
struct bSoundListener;
|
struct bSoundListener;
|
||||||
struct BMF_Font;
|
struct BMF_Font;
|
||||||
|
|
||||||
|
#define UNDO_MAX 64
|
||||||
|
#define UNDO_EDIT_MAX 64
|
||||||
|
|
||||||
|
typedef struct UndoBufferEdit {
|
||||||
|
|
||||||
|
void *datablock;
|
||||||
|
char name[64];
|
||||||
|
|
||||||
|
} UndoBufferEdit;
|
||||||
|
|
||||||
|
|
||||||
typedef struct Global {
|
typedef struct Global {
|
||||||
|
|
||||||
/* active pointers */
|
/* active pointers */
|
||||||
@@ -143,7 +154,15 @@ typedef struct Global {
|
|||||||
short special1, special2;
|
short special1, special2;
|
||||||
|
|
||||||
int flags;
|
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;
|
||||||
|
|
||||||
/* **************** GLOBAL ********************* */
|
/* **************** GLOBAL ********************* */
|
||||||
|
|||||||
@@ -142,5 +142,13 @@ void sort_faces(void);
|
|||||||
void vertices_to_sphere(void);
|
void vertices_to_sphere(void);
|
||||||
void fill_mesh(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
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ typedef struct UserDef {
|
|||||||
short menuthreshold1, menuthreshold2;
|
short menuthreshold1, menuthreshold2;
|
||||||
char fontname[64];
|
char fontname[64];
|
||||||
struct ListBase themes;
|
struct ListBase themes;
|
||||||
|
short undosteps, pad0[3];
|
||||||
} UserDef;
|
} UserDef;
|
||||||
|
|
||||||
extern UserDef U; /* from usiblender.c !!!! */
|
extern UserDef U; /* from usiblender.c !!!! */
|
||||||
|
|||||||
@@ -1473,10 +1473,12 @@ void do_meshbuts(unsigned short event)
|
|||||||
allqueue (REDRAWVIEW3D, 1);
|
allqueue (REDRAWVIEW3D, 1);
|
||||||
break;
|
break;
|
||||||
case B_ASSIGNVGROUP:
|
case B_ASSIGNVGROUP:
|
||||||
|
undo_push_mesh("Assign to vertex group");
|
||||||
assign_verts_defgroup ();
|
assign_verts_defgroup ();
|
||||||
allqueue (REDRAWVIEW3D, 1);
|
allqueue (REDRAWVIEW3D, 1);
|
||||||
break;
|
break;
|
||||||
case B_REMOVEVGROUP:
|
case B_REMOVEVGROUP:
|
||||||
|
undo_push_mesh("Remove from vertex group");
|
||||||
remove_verts_defgroup (0);
|
remove_verts_defgroup (0);
|
||||||
allqueue (REDRAWVIEW3D, 1);
|
allqueue (REDRAWVIEW3D, 1);
|
||||||
break;
|
break;
|
||||||
@@ -1577,11 +1579,13 @@ void do_meshbuts(unsigned short event)
|
|||||||
G.f -= G_DISABLE_OK;
|
G.f -= G_DISABLE_OK;
|
||||||
break;
|
break;
|
||||||
case B_REMDOUB:
|
case B_REMDOUB:
|
||||||
|
undo_push_mesh("Rem Doubles");
|
||||||
notice("Removed: %d", removedoublesflag(1, doublimit));
|
notice("Removed: %d", removedoublesflag(1, doublimit));
|
||||||
allqueue(REDRAWVIEW3D, 0);
|
allqueue(REDRAWVIEW3D, 0);
|
||||||
break;
|
break;
|
||||||
case B_SUBDIV:
|
case B_SUBDIV:
|
||||||
waitcursor(1);
|
waitcursor(1);
|
||||||
|
undo_push_mesh("Subdivide");
|
||||||
subdivideflag(1, 0.0, editbutflag & B_BEAUTY);
|
subdivideflag(1, 0.0, editbutflag & B_BEAUTY);
|
||||||
countall();
|
countall();
|
||||||
waitcursor(0);
|
waitcursor(0);
|
||||||
@@ -1591,6 +1595,7 @@ void do_meshbuts(unsigned short event)
|
|||||||
randfac= 10;
|
randfac= 10;
|
||||||
if(button(&randfac, 1, 100, "Rand fac:")==0) return;
|
if(button(&randfac, 1, 100, "Rand fac:")==0) return;
|
||||||
waitcursor(1);
|
waitcursor(1);
|
||||||
|
undo_push_mesh("Fractal Subdivide");
|
||||||
fac= -( (float)randfac )/100;
|
fac= -( (float)randfac )/100;
|
||||||
subdivideflag(1, fac, editbutflag & B_BEAUTY);
|
subdivideflag(1, fac, editbutflag & B_BEAUTY);
|
||||||
countall();
|
countall();
|
||||||
|
|||||||
@@ -697,6 +697,7 @@ void do_common_editbuts(unsigned short event) // old name, is a mix of object an
|
|||||||
case B_MATASS:
|
case B_MATASS:
|
||||||
if(G.obedit && G.obedit->actcol>0) {
|
if(G.obedit && G.obedit->actcol>0) {
|
||||||
if(G.obedit->type == OB_MESH) {
|
if(G.obedit->type == OB_MESH) {
|
||||||
|
undo_push_mesh("Assign material index");
|
||||||
evl= G.edvl.first;
|
evl= G.edvl.first;
|
||||||
while(evl) {
|
while(evl) {
|
||||||
if( vlakselectedAND(evl, 1) )
|
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) {
|
||||||
if(G.obedit->type == OB_MESH) {
|
if(G.obedit->type == OB_MESH) {
|
||||||
evl= G.edvl.first;
|
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) {
|
while(evl) {
|
||||||
if( vlakselectedAND(evl, 1) ) {
|
if( vlakselectedAND(evl, 1) ) {
|
||||||
if(event==B_SETSMOOTH) evl->flag |= ME_SMOOTH;
|
if(event==B_SETSMOOTH) evl->flag |= ME_SMOOTH;
|
||||||
|
|||||||
@@ -61,6 +61,7 @@
|
|||||||
#include "DNA_view3d_types.h"
|
#include "DNA_view3d_types.h"
|
||||||
#include "DNA_material_types.h"
|
#include "DNA_material_types.h"
|
||||||
#include "DNA_texture_types.h"
|
#include "DNA_texture_types.h"
|
||||||
|
#include "DNA_userdef_types.h"
|
||||||
|
|
||||||
#include "BKE_utildefines.h"
|
#include "BKE_utildefines.h"
|
||||||
#include "BKE_key.h"
|
#include "BKE_key.h"
|
||||||
@@ -102,6 +103,9 @@
|
|||||||
static void free_editverts(ListBase *edve);
|
static void free_editverts(ListBase *edve);
|
||||||
static float convex(float *v1, float *v2, float *v3, float *v4);
|
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 *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HashEdge *hashedgetab=0;
|
struct HashEdge *hashedgetab=NULL;
|
||||||
|
|
||||||
/********* qsort routines *********/
|
/********* qsort routines *********/
|
||||||
|
|
||||||
@@ -935,6 +939,21 @@ static void free_editvert (EditVert *eve)
|
|||||||
void make_editMesh(void)
|
void make_editMesh(void)
|
||||||
{
|
{
|
||||||
Mesh *me;
|
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;
|
MFace *mface;
|
||||||
TFace *tface;
|
TFace *tface;
|
||||||
MVert *mvert;
|
MVert *mvert;
|
||||||
@@ -948,7 +967,6 @@ void make_editMesh(void)
|
|||||||
/* because of reload */
|
/* because of reload */
|
||||||
free_editMesh();
|
free_editMesh();
|
||||||
|
|
||||||
me= get_mesh(G.obedit);
|
|
||||||
G.totvert= tot= me->totvert;
|
G.totvert= tot= me->totvert;
|
||||||
|
|
||||||
if(tot==0) {
|
if(tot==0) {
|
||||||
@@ -1167,9 +1185,20 @@ static void fix_faceindices(MFace *mface, EditVlak *evl, int nr)
|
|||||||
|
|
||||||
/* load from EditMode to Mesh */
|
/* load from EditMode to Mesh */
|
||||||
|
|
||||||
void load_editMesh(void)
|
void load_editMesh()
|
||||||
{
|
{
|
||||||
Mesh *me;
|
Mesh *me;
|
||||||
|
|
||||||
|
waitcursor(1);
|
||||||
|
countall();
|
||||||
|
me= get_mesh(G.obedit);
|
||||||
|
|
||||||
|
load_editMesh_real(me);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void load_editMesh_real(Mesh *me)
|
||||||
|
{
|
||||||
MFace *mface;
|
MFace *mface;
|
||||||
MVert *mvert;
|
MVert *mvert;
|
||||||
MSticky *ms;
|
MSticky *ms;
|
||||||
@@ -1184,11 +1213,6 @@ void load_editMesh(void)
|
|||||||
int usedDvert = 0;
|
int usedDvert = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
waitcursor(1);
|
|
||||||
countall();
|
|
||||||
|
|
||||||
me= get_mesh(G.obedit);
|
|
||||||
|
|
||||||
ototvert= me->totvert;
|
ototvert= me->totvert;
|
||||||
|
|
||||||
/* are there keys? */
|
/* are there keys? */
|
||||||
@@ -1478,9 +1502,7 @@ void load_editMesh(void)
|
|||||||
|
|
||||||
void remake_editMesh(void)
|
void remake_editMesh(void)
|
||||||
{
|
{
|
||||||
|
undo_push_mesh("Undo all changes");
|
||||||
if(okee("Reload Original data")==0) return;
|
|
||||||
|
|
||||||
make_editMesh();
|
make_editMesh();
|
||||||
allqueue(REDRAWVIEW3D, 0);
|
allqueue(REDRAWVIEW3D, 0);
|
||||||
makeDispList(G.obedit);
|
makeDispList(G.obedit);
|
||||||
@@ -1651,6 +1673,8 @@ void convert_to_triface(int all)
|
|||||||
{
|
{
|
||||||
EditVlak *evl, *evln, *next;
|
EditVlak *evl, *evln, *next;
|
||||||
|
|
||||||
|
undo_push_mesh("Convert to triangles");
|
||||||
|
|
||||||
evl= G.edvl.first;
|
evl= G.edvl.first;
|
||||||
while(evl) {
|
while(evl) {
|
||||||
next= evl->next;
|
next= evl->next;
|
||||||
@@ -1695,6 +1719,10 @@ void deselectall_mesh(void) /* toggle */
|
|||||||
}
|
}
|
||||||
eve= eve->next;
|
eve= eve->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (a) undo_push_mesh("Deselect all");
|
||||||
|
else undo_push_mesh("Select all");
|
||||||
|
|
||||||
eve= G.edve.first;
|
eve= G.edve.first;
|
||||||
while(eve) {
|
while(eve) {
|
||||||
if(eve->h==0) {
|
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 ...' */
|
/* in case (selected) faces were not done: start over with 'find the ultimate ...' */
|
||||||
|
|
||||||
waitcursor(1);
|
waitcursor(1);
|
||||||
|
|
||||||
|
if (select==2) undo_push_mesh("Recalc normals inside");
|
||||||
|
if (select==1) undo_push_mesh("Recalc normals outside");
|
||||||
|
|
||||||
eed= G.eded.first;
|
eed= G.eded.first;
|
||||||
while(eed) {
|
while(eed) {
|
||||||
@@ -2331,6 +2362,7 @@ void edge_select(void)
|
|||||||
if( (G.qual & LR_SHIFTKEY)==0) {
|
if( (G.qual & LR_SHIFTKEY)==0) {
|
||||||
EditVert *eve;
|
EditVert *eve;
|
||||||
|
|
||||||
|
undo_push_mesh("Edge select");
|
||||||
/* deselectall */
|
/* deselectall */
|
||||||
for(eve= G.edve.first; eve; eve= eve->next) eve->f&= ~1;
|
for(eve= G.edve.first; eve; eve= eve->next) eve->f&= ~1;
|
||||||
|
|
||||||
@@ -2367,6 +2399,7 @@ void mouse_mesh(void)
|
|||||||
if(act) {
|
if(act) {
|
||||||
|
|
||||||
if((G.qual & LR_SHIFTKEY)==0) {
|
if((G.qual & LR_SHIFTKEY)==0) {
|
||||||
|
undo_push_mesh("Vertex select");
|
||||||
tekenvertices_special(0, act);
|
tekenvertices_special(0, act);
|
||||||
}
|
}
|
||||||
if( (act->f & 1)==0) act->f+= 1;
|
if( (act->f & 1)==0) act->f+= 1;
|
||||||
@@ -2387,6 +2420,8 @@ static void selectconnectedAll(void)
|
|||||||
short flag=1,toggle=0;
|
short flag=1,toggle=0;
|
||||||
|
|
||||||
if(G.eded.first==0) return;
|
if(G.eded.first==0) return;
|
||||||
|
|
||||||
|
undo_push_mesh("Select Connected (All)");
|
||||||
|
|
||||||
while(flag==1) {
|
while(flag==1) {
|
||||||
flag= 0;
|
flag= 0;
|
||||||
@@ -2441,7 +2476,8 @@ void selectconnected_mesh(void)
|
|||||||
error(" Nothing indicated ");
|
error(" Nothing indicated ");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
undo_push_mesh("Select linked");
|
||||||
/* clear test flags */
|
/* clear test flags */
|
||||||
eve= G.edve.first;
|
eve= G.edve.first;
|
||||||
while(eve) {
|
while(eve) {
|
||||||
@@ -3001,6 +3037,8 @@ void xsortvert_flag(int flag)
|
|||||||
}
|
}
|
||||||
if(aantal==0) return;
|
if(aantal==0) return;
|
||||||
|
|
||||||
|
undo_push_mesh("Xsort");
|
||||||
|
|
||||||
/* allocate memory and sort */
|
/* allocate memory and sort */
|
||||||
sb= sortblock= (struct xvertsort *)MEM_mallocN(sizeof(struct xvertsort)*aantal,"sortremovedoub");
|
sb= sortblock= (struct xvertsort *)MEM_mallocN(sizeof(struct xvertsort)*aantal,"sortremovedoub");
|
||||||
eve= G.edve.first;
|
eve= G.edve.first;
|
||||||
@@ -3046,6 +3084,8 @@ void hashvert_flag(int flag)
|
|||||||
eve= eve->next;
|
eve= eve->next;
|
||||||
}
|
}
|
||||||
if(aantal==0) return;
|
if(aantal==0) return;
|
||||||
|
|
||||||
|
undo_push_mesh("Hash");
|
||||||
|
|
||||||
/* allocate memory */
|
/* allocate memory */
|
||||||
sb= sortblock= (struct xvertsort *)MEM_mallocN(sizeof(struct xvertsort)*aantal,"sortremovedoub");
|
sb= sortblock= (struct xvertsort *)MEM_mallocN(sizeof(struct xvertsort)*aantal,"sortremovedoub");
|
||||||
@@ -3882,9 +3922,10 @@ void extrude_mesh(void)
|
|||||||
TEST_EDITMESH
|
TEST_EDITMESH
|
||||||
|
|
||||||
if(okee("Extrude")==0) return;
|
if(okee("Extrude")==0) return;
|
||||||
|
|
||||||
waitcursor(1);
|
waitcursor(1);
|
||||||
|
undo_push_mesh("Extrude");
|
||||||
|
|
||||||
a= extrudeflag(1,1);
|
a= extrudeflag(1,1);
|
||||||
waitcursor(0);
|
waitcursor(0);
|
||||||
if(a==0) {
|
if(a==0) {
|
||||||
@@ -3904,9 +3945,9 @@ void adduplicate_mesh(void)
|
|||||||
TEST_EDITMESH
|
TEST_EDITMESH
|
||||||
|
|
||||||
waitcursor(1);
|
waitcursor(1);
|
||||||
|
undo_push_mesh("Duplicate");
|
||||||
adduplicateflag(1);
|
adduplicateflag(1);
|
||||||
waitcursor(0);
|
waitcursor(0);
|
||||||
|
|
||||||
countall(); /* for G.totvert in calc_meshverts() */
|
countall(); /* for G.totvert in calc_meshverts() */
|
||||||
transform('d');
|
transform('d');
|
||||||
}
|
}
|
||||||
@@ -3919,7 +3960,7 @@ void split_mesh(void)
|
|||||||
if(okee(" Split ")==0) return;
|
if(okee(" Split ")==0) return;
|
||||||
|
|
||||||
waitcursor(1);
|
waitcursor(1);
|
||||||
|
undo_push_mesh("Split");
|
||||||
/* make duplicate first */
|
/* make duplicate first */
|
||||||
adduplicateflag(1);
|
adduplicateflag(1);
|
||||||
/* old faces have 3x flag 128 set, delete them */
|
/* old faces have 3x flag 128 set, delete them */
|
||||||
@@ -3937,8 +3978,11 @@ void separatemenu(void)
|
|||||||
{
|
{
|
||||||
short event;
|
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) {
|
switch (event) {
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
@@ -3948,6 +3992,7 @@ void separatemenu(void)
|
|||||||
separate_mesh_loose();
|
separate_mesh_loose();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
waitcursor(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -4290,6 +4335,8 @@ void extrude_repeat_mesh(int steps, float offs)
|
|||||||
|
|
||||||
TEST_EDITMESH
|
TEST_EDITMESH
|
||||||
waitcursor(1);
|
waitcursor(1);
|
||||||
|
|
||||||
|
undo_push_mesh("Extrude Repeat");
|
||||||
|
|
||||||
/* dvec */
|
/* dvec */
|
||||||
dvec[0]= G.vd->persinv[2][0];
|
dvec[0]= G.vd->persinv[2][0];
|
||||||
@@ -4331,6 +4378,8 @@ void spin_mesh(int steps,int degr,float *dvec, int mode)
|
|||||||
TEST_EDITMESH
|
TEST_EDITMESH
|
||||||
|
|
||||||
waitcursor(1);
|
waitcursor(1);
|
||||||
|
|
||||||
|
undo_push_mesh("Spin");
|
||||||
|
|
||||||
/* imat and centre and size */
|
/* imat and centre and size */
|
||||||
Mat3CpyMat4(bmat, G.obedit->obmat);
|
Mat3CpyMat4(bmat, G.obedit->obmat);
|
||||||
@@ -4417,7 +4466,9 @@ void screw_mesh(int steps,int turns)
|
|||||||
error("Only in frontview!");
|
error("Only in frontview!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
undo_push_mesh("Screw");
|
||||||
|
|
||||||
/* clear flags */
|
/* clear flags */
|
||||||
eve= G.edve.first;
|
eve= G.edve.first;
|
||||||
while(eve) {
|
while(eve) {
|
||||||
@@ -4668,11 +4719,13 @@ void delete_mesh(void)
|
|||||||
if(event<1) return;
|
if(event<1) return;
|
||||||
|
|
||||||
if(event==10 ) {
|
if(event==10 ) {
|
||||||
|
undo_push_mesh("Erase Vertices");
|
||||||
erase_edges(&G.eded);
|
erase_edges(&G.eded);
|
||||||
erase_faces(&G.edvl);
|
erase_faces(&G.edvl);
|
||||||
erase_vertices(&G.edve);
|
erase_vertices(&G.edve);
|
||||||
}
|
}
|
||||||
else if(event==4) {
|
else if(event==4) {
|
||||||
|
undo_push_mesh("Erase Edges & Faces");
|
||||||
evl= G.edvl.first;
|
evl= G.edvl.first;
|
||||||
while(evl) {
|
while(evl) {
|
||||||
nextvl= evl->next;
|
nextvl= evl->next;
|
||||||
@@ -4714,6 +4767,7 @@ void delete_mesh(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(event==1) {
|
else if(event==1) {
|
||||||
|
undo_push_mesh("Erase Edges");
|
||||||
eed= G.eded.first;
|
eed= G.eded.first;
|
||||||
while(eed) {
|
while(eed) {
|
||||||
nexted= eed->next;
|
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) {
|
else if(event==3) {
|
||||||
|
undo_push_mesh("Erase All");
|
||||||
// if(G.edve.first) BLI_freelist(&G.edve);
|
// if(G.edve.first) BLI_freelist(&G.edve);
|
||||||
if(G.edve.first) free_editverts(&G.edve);
|
if(G.edve.first) free_editverts(&G.edve);
|
||||||
if(G.eded.first) BLI_freelist(&G.eded);
|
if(G.eded.first) BLI_freelist(&G.eded);
|
||||||
if(G.edvl.first) freevlaklist(&G.edvl);
|
if(G.edvl.first) freevlaklist(&G.edvl);
|
||||||
}
|
}
|
||||||
else if(event==5) {
|
else if(event==5) {
|
||||||
|
undo_push_mesh("Erase Only Faces");
|
||||||
evl= G.edvl.first;
|
evl= G.edvl.first;
|
||||||
while(evl) {
|
while(evl) {
|
||||||
nextvl= evl->next;
|
nextvl= evl->next;
|
||||||
@@ -5175,6 +5234,8 @@ void vertexsmooth(void)
|
|||||||
eve= eve->next;
|
eve= eve->next;
|
||||||
}
|
}
|
||||||
if(teller==0) return;
|
if(teller==0) return;
|
||||||
|
|
||||||
|
undo_push_mesh("Smooth");
|
||||||
|
|
||||||
adr=adror= (float *)MEM_callocN(3*sizeof(float *)*teller, "vertsmooth");
|
adr=adror= (float *)MEM_callocN(3*sizeof(float *)*teller, "vertsmooth");
|
||||||
eve= G.edve.first;
|
eve= G.edve.first;
|
||||||
@@ -5237,7 +5298,9 @@ void vertexnoise(void)
|
|||||||
float b2, ofs, vec[3];
|
float b2, ofs, vec[3];
|
||||||
|
|
||||||
if(G.obedit==0) return;
|
if(G.obedit==0) return;
|
||||||
|
|
||||||
|
undo_push_mesh("Noise");
|
||||||
|
|
||||||
ma= give_current_material(G.obedit, G.obedit->actcol);
|
ma= give_current_material(G.obedit, G.obedit->actcol);
|
||||||
if(ma==0 || ma->mtex[0]==0 || ma->mtex[0]->tex==0) {
|
if(ma==0 || ma->mtex[0]==0 || ma->mtex[0]->tex==0) {
|
||||||
return;
|
return;
|
||||||
@@ -5609,6 +5672,8 @@ void join_triangles(void)
|
|||||||
totedge = count_edges(G.eded.first);
|
totedge = count_edges(G.eded.first);
|
||||||
if(totedge==0) return;
|
if(totedge==0) return;
|
||||||
|
|
||||||
|
undo_push_mesh("Join triangles");
|
||||||
|
|
||||||
evlar= (EVPTuple *) MEM_callocN(totedge * sizeof(EVPTuple), "jointris");
|
evlar= (EVPTuple *) MEM_callocN(totedge * sizeof(EVPTuple), "jointris");
|
||||||
|
|
||||||
ok = collect_quadedges(evlar, G.eded.first, G.edvl.first);
|
ok = collect_quadedges(evlar, G.eded.first, G.edvl.first);
|
||||||
@@ -5702,6 +5767,8 @@ void edge_flip(void)
|
|||||||
totedge = count_edges(G.eded.first);
|
totedge = count_edges(G.eded.first);
|
||||||
if(totedge==0) return;
|
if(totedge==0) return;
|
||||||
|
|
||||||
|
undo_push_mesh("Flip edges");
|
||||||
|
|
||||||
/* temporary array for : edge -> face[1], face[2] */
|
/* temporary array for : edge -> face[1], face[2] */
|
||||||
evlar= (EVPTuple *) MEM_callocN(totedge * sizeof(EVPTuple), "edgeflip");
|
evlar= (EVPTuple *) MEM_callocN(totedge * sizeof(EVPTuple), "edgeflip");
|
||||||
|
|
||||||
@@ -5808,6 +5875,8 @@ void beauty_fill(void)
|
|||||||
if(totedge==0) return;
|
if(totedge==0) return;
|
||||||
|
|
||||||
if(okee("Beauty Fill")==0) return;
|
if(okee("Beauty Fill")==0) return;
|
||||||
|
|
||||||
|
undo_push_mesh("Beauty Fill");
|
||||||
|
|
||||||
/* temp block with face pointers */
|
/* temp block with face pointers */
|
||||||
evlar= (EVPTuple *) MEM_callocN(totedge * sizeof(EVPTuple), "beautyfill");
|
evlar= (EVPTuple *) MEM_callocN(totedge * sizeof(EVPTuple), "beautyfill");
|
||||||
@@ -6360,6 +6429,9 @@ void vertices_to_sphere(void)
|
|||||||
TEST_EDITMESH
|
TEST_EDITMESH
|
||||||
|
|
||||||
if(button(&perc, 1, 100, "Percentage:")==0) return;
|
if(button(&perc, 1, 100, "Percentage:")==0) return;
|
||||||
|
|
||||||
|
undo_push_mesh("To Sphere");
|
||||||
|
|
||||||
fac= perc/100.0;
|
fac= perc/100.0;
|
||||||
facm= 1.0-fac;
|
facm= 1.0-fac;
|
||||||
|
|
||||||
@@ -6421,6 +6493,8 @@ void fill_mesh(void)
|
|||||||
|
|
||||||
waitcursor(1);
|
waitcursor(1);
|
||||||
|
|
||||||
|
undo_push_mesh("Fill");
|
||||||
|
|
||||||
/* copy all selected vertices */
|
/* copy all selected vertices */
|
||||||
eve= G.edve.first;
|
eve= G.edve.first;
|
||||||
while(eve) {
|
while(eve) {
|
||||||
@@ -6998,7 +7072,9 @@ void KnifeSubdivide(char mode){
|
|||||||
|
|
||||||
if (G.obedit==0) return;
|
if (G.obedit==0) return;
|
||||||
|
|
||||||
/* Set a knife cursor here ??? */
|
undo_push_mesh("Knife");
|
||||||
|
|
||||||
|
/* Set a knife cursor here */
|
||||||
oldcursor=get_cursor();
|
oldcursor=get_cursor();
|
||||||
set_cursor(CURSOR_PENCIL);
|
set_cursor(CURSOR_PENCIL);
|
||||||
|
|
||||||
@@ -7150,3 +7226,156 @@ short seg_intersect(EditEdge *e, CutCurve *c, int len){
|
|||||||
return(isect);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1500,21 +1500,25 @@ void special_editmenu(void)
|
|||||||
|
|
||||||
switch(nr) {
|
switch(nr) {
|
||||||
case 1:
|
case 1:
|
||||||
|
undo_push_mesh("Subdivide");
|
||||||
subdivideflag(1, 0.0, editbutflag);
|
subdivideflag(1, 0.0, editbutflag);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
randfac= 10;
|
randfac= 10;
|
||||||
if(button(&randfac, 1, 100, "Rand fac:")==0) return;
|
if(button(&randfac, 1, 100, "Rand fac:")==0) return;
|
||||||
fac= -( (float)randfac )/100;
|
fac= -( (float)randfac )/100;
|
||||||
|
undo_push_mesh("Subdivide Fractal");
|
||||||
subdivideflag(1, fac, editbutflag);
|
subdivideflag(1, fac, editbutflag);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
|
undo_push_mesh("Subdivide Smooth");
|
||||||
subdivideflag(1, 0.0, editbutflag | B_SMOOTH);
|
subdivideflag(1, 0.0, editbutflag | B_SMOOTH);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
mergemenu();
|
mergemenu();
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
|
undo_push_mesh("Rem Doubles");
|
||||||
notice("Removed: %d", removedoublesflag(1, doublimit));
|
notice("Removed: %d", removedoublesflag(1, doublimit));
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
@@ -1553,9 +1557,6 @@ void special_editmenu(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
countall();
|
countall();
|
||||||
allqueue(REDRAWVIEW3D, 0);
|
allqueue(REDRAWVIEW3D, 0);
|
||||||
|
|
||||||
@@ -3743,6 +3744,24 @@ void view_editmove(unsigned char event)
|
|||||||
break;
|
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' */
|
void transform(int mode) /* 'g' 'G' 'r' 'R' 's' 'S' 't' or 'w' 'N' */
|
||||||
{
|
{
|
||||||
short canceled = 0;
|
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(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? */
|
/* what data will be involved? */
|
||||||
if(G.obedit) {
|
if(G.obedit) {
|
||||||
if(mode=='N') vertexnormals(0);
|
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) {
|
if(event==ESCKEY || event==RIGHTMOUSE) {
|
||||||
canceled=1;
|
canceled=1;
|
||||||
|
G.undo_edit_level--;
|
||||||
tv= transvmain;
|
tv= transvmain;
|
||||||
tob= transmain;
|
tob= transmain;
|
||||||
for(a=0; a<tottrans; a++, tob++, tv++) {
|
for(a=0; a<tottrans; a++, tob++, tv++) {
|
||||||
|
|||||||
@@ -1168,7 +1168,11 @@ void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
|
|||||||
break;
|
break;
|
||||||
case UKEY:
|
case UKEY:
|
||||||
if(G.obedit) {
|
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(G.obedit->type==OB_ARMATURE) remake_editArmature();
|
||||||
else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) remake_editNurb();
|
else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) remake_editNurb();
|
||||||
else if(G.obedit->type==OB_LATTICE) remake_editLatt();
|
else if(G.obedit->type==OB_LATTICE) remake_editLatt();
|
||||||
@@ -1881,7 +1885,9 @@ void drawinfospace(ScrArea *sa, void *spacedata)
|
|||||||
|
|
||||||
uiBlockSetCol(block, BUTGREY);
|
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:",
|
uiDefBut(block, LABEL,0,"Auto keyframe on:",
|
||||||
(xpos+edgespace+(2*medprefbut)+midspace),y3label,medprefbut,buth,
|
(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",
|
uiDefButS(block, TOG|BIT|6, 0, "Ipo",
|
||||||
(xpos+edgespace+(8*midspace)+(3*medprefbut)+(5*smallprefbut)),y1,smallprefbut,buth,
|
(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");
|
&(U.dupflag), 0, 0, 0, 0, "Causes ipo data to be duplicated with Shift+D");
|
||||||
|
|
||||||
|
|
||||||
} else if(U.userpref == 2) { /* language & colors */
|
} else if(U.userpref == 2) { /* language & colors */
|
||||||
|
|
||||||
#ifdef INTERNATIONAL
|
#ifdef INTERNATIONAL
|
||||||
|
|||||||
@@ -65,6 +65,7 @@
|
|||||||
#include "DNA_object_types.h"
|
#include "DNA_object_types.h"
|
||||||
#include "DNA_space_types.h"
|
#include "DNA_space_types.h"
|
||||||
#include "DNA_userdef_types.h"
|
#include "DNA_userdef_types.h"
|
||||||
|
#include "DNA_mesh_types.h"
|
||||||
|
|
||||||
#include "BKE_blender.h"
|
#include "BKE_blender.h"
|
||||||
#include "BKE_curve.h"
|
#include "BKE_curve.h"
|
||||||
@@ -225,6 +226,8 @@ int BIF_read_homefile(void)
|
|||||||
U.mixbufsize= 2048;
|
U.mixbufsize= 2048;
|
||||||
}
|
}
|
||||||
space_set_commmandline_options();
|
space_set_commmandline_options();
|
||||||
|
|
||||||
|
if (U.undosteps==0) U.undosteps=32;
|
||||||
|
|
||||||
reset_autosave();
|
reset_autosave();
|
||||||
}
|
}
|
||||||
@@ -564,6 +567,8 @@ void exit_usiblender(void)
|
|||||||
mainwindow_close();
|
mainwindow_close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (G.undo_clear) G.undo_clear();
|
||||||
|
|
||||||
BLI_freelistN(&U.themes);
|
BLI_freelistN(&U.themes);
|
||||||
|
|
||||||
if(totblock!=0) {
|
if(totblock!=0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user