-> Stored Selections

Previously Blender did not store the order in which vertices, edges
or faces were selected in edit mode. In many cases it is useful to
have this data, however it is not desirable to store every selection
made. Now blender stores selections in the order in which they were
made in a linked list called 'selected' in  EditMesh. EditSelection structs
are created whenever 'EM_store_selection' from  editmesh_lib.c is called
(currently only on user selection with mouse). There are several cases
in which they might be deallocated by calling the 'EM_remove_selection'
function however:

-When the user deselects something with the mouse ('mouse_mesh' in
 editmesh_mods.c)

-When switching selection modes stored selections that are not relevant
to the new mode are removed by the 'EM_strip_selections' function
(multi-select mode is supported)

-When the vertex, edge or face pointed to by a certain stored selection is
deallocated

-When EM_clear_flag_all is called and where the flag passed to the function
contains the 'SELECT' bitmask.

-When leaving edit mode (making stored selection data persistent across
editing sessions will require modifications to mesh DNA later)

Todo:

There are a few cases still where you can temporarily end up with a stored
selection that points to an element that is no longer selected
(edge loop de-select can cause this for instance). The solution to this is to
add a call to EM_remove_selection from 'EM_select_edge' and 'EM_select_face' when
these functions are being used to deselect elements. For the sake of completeness
however this will also require that an 'EM_select_vert' function be coded and
called at all appropriate parts of the editmesh code. I will look into this
later in the week.

For now there are two tools that already take advantage of the stored selections.
The first one is 'merge at first or last vertex' in the merge menu (the 'firstvert' and
'lastvert' pointers are gone from EditMesh). The second tool is path select, which builds
a path between the last vert selected and the second to last vert selected. This allows you
to build complex path selections in a short amount of time like this
'select A, select B, path select. select C, path select. select D...'
This commit is contained in:
Geoffrey Bantle 2006-03-27 05:19:14 +00:00
parent 07b88496e0
commit 7b1d69a35c
7 changed files with 185 additions and 84 deletions

@ -126,19 +126,30 @@ typedef struct EditFace
unsigned char fgonf; /* flag for fgon options */ unsigned char fgonf; /* flag for fgon options */
} EditFace; } EditFace;
/*selection types*/
#define EDITVERT 0
#define EDITEDGE 1
#define EDITFACE 2
typedef struct EditSelection
{
struct EditSelection *next, *prev;
short type;
void *data;
} EditSelection;
typedef struct EditMesh typedef struct EditMesh
{ {
ListBase verts, edges, faces; ListBase verts, edges, faces;
ListBase selected; /*EditSelections. Used to store the order in which things are selected.*/
HashEdge *hashedgetab; HashEdge *hashedgetab;
/* this is for the editmesh_fastmalloc */ /* this is for the editmesh_fastmalloc */
EditVert *allverts, *curvert; EditVert *allverts, *curvert;
EditEdge *alledges, *curedge; EditEdge *alledges, *curedge;
EditFace *allfaces, *curface; EditFace *allfaces, *curface;
/*for improved merge code*/
EditVert *lastvert, *firstvert;
/* DerivedMesh caches... note that derived cage can be equivalent /* DerivedMesh caches... note that derived cage can be equivalent
* to derived final, care should be taken on release. * to derived final, care should be taken on release.
*/ */

@ -84,6 +84,8 @@ extern void EM_select_flush(void); // vertices to edges/faces (exception!)
extern void EM_selectmode_set(void); // when mode changes extern void EM_selectmode_set(void); // when mode changes
extern void EM_selectmode_flush(void); // when selection changes extern void EM_selectmode_flush(void); // when selection changes
extern void EM_convertsel(short oldmode, short selectmode); extern void EM_convertsel(short oldmode, short selectmode);
extern void EM_remove_selection(void *data, int type);
extern void EM_store_selection(void *data, int type);
extern int EM_nfaces_selected(void); extern int EM_nfaces_selected(void);
extern int EM_nvertices_selected(void); extern int EM_nvertices_selected(void);

@ -602,16 +602,7 @@ void countall()
if(efa->f & SELECT) G.totfacesel++; if(efa->f & SELECT) G.totfacesel++;
} }
/*for keeping track of last & first vertex selected*/ /*add code to strip editselections*/
/*lastvert and first must be cleared in two circumstances.....*/
// 1: if last/first vert exists but is NOT selected, get rid of it.
// 2: if totvertsel = 0, get rid of last/first vert
if((G.editMesh->lastvert) && ( !(G.editMesh->lastvert->f&SELECT) )) G.editMesh->lastvert = NULL;
else if(G.totvertsel == 0) G.editMesh->lastvert = NULL;
if((G.editMesh->firstvert) && ( !(G.editMesh->firstvert->f&SELECT) )) G.editMesh->firstvert = NULL;
else if(G.totvertsel == 0) G.editMesh->firstvert = NULL;
} }
else if (G.obedit->type==OB_ARMATURE){ else if (G.obedit->type==OB_ARMATURE){
for (ebo=G.edbo.first;ebo;ebo=ebo->next){ for (ebo=G.edbo.first;ebo;ebo=ebo->next){
@ -1572,9 +1563,13 @@ void mergemenu(void)
int remCount = 0; int remCount = 0;
if(G.scene->selectmode == SCE_SELECT_VERTEX) if(G.scene->selectmode == SCE_SELECT_VERTEX)
if(G.editMesh->firstvert && G.editMesh->lastvert) event = pupmenu("Merge %t|At First %x6|At Last%x1|At Center%x3|At Cursor%x4"); if(G.editMesh->selected.first && G.editMesh->selected.last &&
else if (G.editMesh->firstvert) event = pupmenu("Merge %t|At First %x6|At Center%x3|At Cursor%x4"); ((EditSelection*)G.editMesh->selected.first)->type == EDITVERT && ((EditSelection*)G.editMesh->selected.last)->type == EDITVERT)
else if (G.editMesh->lastvert) event = pupmenu("Merge %t|At Last %x1|At Center%x3|At Cursor%x4"); event = pupmenu("Merge %t|At First %x6|At Last%x1|At Center%x3|At Cursor%x4");
else if (G.editMesh->selected.first && ((EditSelection*)G.editMesh->selected.first)->type == EDITVERT)
event = pupmenu("Merge %t|At First %x6|At Center%x3|At Cursor%x4");
else if (G.editMesh->selected.last && ((EditSelection*)G.editMesh->selected.last)->type == EDITVERT)
event = pupmenu("Merge %t|At Last %x1|At Center%x3|At Cursor%x4");
else event = pupmenu("Merge %t|At Center%x3|At Cursor%x4"); else event = pupmenu("Merge %t|At Center%x3|At Cursor%x4");
else if(G.scene->selectmode == SCE_SELECT_EDGE) else if(G.scene->selectmode == SCE_SELECT_EDGE)

@ -147,7 +147,10 @@ EditVert *addvertlist(float *vec)
void free_editvert (EditVert *eve) void free_editvert (EditVert *eve)
{ {
if(eve->dw) MEM_freeN(eve->dw); if(eve->dw) MEM_freeN(eve->dw);
if(eve->fast==0) free(eve); EM_remove_selection(eve, EDITVERT);
if(eve->fast==0){
free(eve);
}
} }
@ -277,12 +280,18 @@ void remedge(EditEdge *eed)
void free_editedge(EditEdge *eed) void free_editedge(EditEdge *eed)
{ {
if(eed->fast==0) free(eed); EM_remove_selection(eed, EDITEDGE);
if(eed->fast==0){
free(eed);
}
} }
void free_editface(EditFace *efa) void free_editface(EditFace *efa)
{ {
if(efa->fast==0) free(efa); EM_remove_selection(efa, EDITFACE);
if(efa->fast==0){
free(efa);
}
} }
void free_vertlist(ListBase *edve) void free_vertlist(ListBase *edve)
@ -496,7 +505,7 @@ void free_editMesh(EditMesh *em)
if(em->verts.first) free_vertlist(&em->verts); if(em->verts.first) free_vertlist(&em->verts);
if(em->edges.first) free_edgelist(&em->edges); if(em->edges.first) free_edgelist(&em->edges);
if(em->faces.first) free_facelist(&em->faces); if(em->faces.first) free_facelist(&em->faces);
if(em->selected.first) BLI_freelistN(&(em->selected));
if(em->derivedFinal) { if(em->derivedFinal) {
if (em->derivedFinal!=em->derivedCage) { if (em->derivedFinal!=em->derivedCage) {
em->derivedFinal->release(em->derivedFinal); em->derivedFinal->release(em->derivedFinal);
@ -1206,9 +1215,7 @@ void load_editMesh(void)
mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL); mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
em->lastvert = NULL; BLI_freelistN(&(em->selected)); /*come up with better solution so leaving editmode and not switching meshes will not nuke this...*/
em->firstvert = NULL;
waitcursor(0); waitcursor(0);
} }
@ -1548,6 +1555,7 @@ void separate_mesh_loose(void)
/* only one 'hack', to save memory it doesn't store the first push, but does a remake editmesh */ /* only one 'hack', to save memory it doesn't store the first push, but does a remake editmesh */
/* a compressed version of editmesh data */ /* a compressed version of editmesh data */
typedef struct EditVertC typedef struct EditVertC
{ {
float no[3]; float no[3];
@ -1572,13 +1580,19 @@ typedef struct EditFaceC
short pad1; short pad1;
} EditFaceC; } EditFaceC;
typedef struct EditSelectionC{
short type;
int index;
}EditSelectionC;
typedef struct UndoMesh { typedef struct UndoMesh {
EditVertC *verts; EditVertC *verts;
EditEdgeC *edges; EditEdgeC *edges;
EditFaceC *faces; EditFaceC *faces;
EditSelectionC *selected;
TFace *tfaces; TFace *tfaces;
int totvert, totedge, totface; int totvert, totedge, totface,totsel;
int lastvert, firstvert; /*index for last and first selected vert. -1 if no first/last vert exists (nasty)*/
short selectmode; short selectmode;
} UndoMesh; } UndoMesh;
@ -1599,6 +1613,7 @@ static void free_undoMesh(void *umv)
if(um->edges) MEM_freeN(um->edges); if(um->edges) MEM_freeN(um->edges);
if(um->faces) MEM_freeN(um->faces); if(um->faces) MEM_freeN(um->faces);
if(um->tfaces) MEM_freeN(um->tfaces); if(um->tfaces) MEM_freeN(um->tfaces);
if(um->selected) MEM_freeN(um->selected);
MEM_freeN(um); MEM_freeN(um);
} }
@ -1610,51 +1625,36 @@ static void *editMesh_to_undoMesh(void)
EditVert *eve; EditVert *eve;
EditEdge *eed; EditEdge *eed;
EditFace *efa; EditFace *efa;
EditSelection *ese;
EditVertC *evec=NULL; EditVertC *evec=NULL;
EditEdgeC *eedc=NULL; EditEdgeC *eedc=NULL;
EditFaceC *efac=NULL; EditFaceC *efac=NULL;
EditSelectionC *esec=NULL;
TFace *tface= NULL; TFace *tface= NULL;
int i, a=0; int i, a;
um= MEM_callocN(sizeof(UndoMesh), "undomesh"); um= MEM_callocN(sizeof(UndoMesh), "undomesh");
um->selectmode = G.scene->selectmode; um->selectmode = G.scene->selectmode;
um->lastvert = -1;
um->firstvert = -1;
if(em->lastvert){
for (i=0,eve=G.editMesh->verts.first; eve; i++,eve=eve->next){
if(eve == em->lastvert){
um->lastvert = i;
break;
}
}
}
if(em->firstvert){
for (i=0,eve=G.editMesh->verts.first; eve; i++,eve=eve->next){
if(eve == em->firstvert){
um->firstvert = i;
break;
}
}
}
for(eve=em->verts.first; eve; eve= eve->next) um->totvert++; for(eve=em->verts.first; eve; eve= eve->next) um->totvert++;
for(eed=em->edges.first; eed; eed= eed->next) um->totedge++; for(eed=em->edges.first; eed; eed= eed->next) um->totedge++;
for(efa=em->faces.first; efa; efa= efa->next) um->totface++; for(efa=em->faces.first; efa; efa= efa->next) um->totface++;
for(ese=em->selected.first; ese; ese=ese->next) um->totsel++;
/* malloc blocks */ /* malloc blocks */
if(um->totvert) evec= um->verts= MEM_callocN(um->totvert*sizeof(EditVertC), "allvertsC"); if(um->totvert) evec= um->verts= MEM_callocN(um->totvert*sizeof(EditVertC), "allvertsC");
if(um->totedge) eedc= um->edges= MEM_callocN(um->totedge*sizeof(EditEdgeC), "alledgesC"); if(um->totedge) eedc= um->edges= MEM_callocN(um->totedge*sizeof(EditEdgeC), "alledgesC");
if(um->totface) efac= um->faces= MEM_callocN(um->totface*sizeof(EditFaceC), "allfacesC"); if(um->totface) efac= um->faces= MEM_callocN(um->totface*sizeof(EditFaceC), "allfacesC");
if(um->totsel) esec= um->selected= MEM_callocN(um->totsel*sizeof(EditSelectionC), "allselections");
if(me->tface || me->mcol) tface= um->tfaces= MEM_mallocN(um->totface*sizeof(TFace), "all tfacesC"); if(me->tface || me->mcol) tface= um->tfaces= MEM_mallocN(um->totface*sizeof(TFace), "all tfacesC");
//printf("copy editmesh %d\n", um->totvert*sizeof(EditVert) + um->totedge*sizeof(EditEdge) + um->totface*sizeof(EditFace)); //printf("copy editmesh %d\n", um->totvert*sizeof(EditVert) + um->totedge*sizeof(EditEdge) + um->totface*sizeof(EditFace));
//printf("copy undomesh %d\n", um->totvert*sizeof(EditVertC) + um->totedge*sizeof(EditEdgeC) + um->totface*sizeof(EditFaceC)); //printf("copy undomesh %d\n", um->totvert*sizeof(EditVertC) + um->totedge*sizeof(EditEdgeC) + um->totface*sizeof(EditFaceC));
/* now copy vertices */ /* now copy vertices */
a = 0;
for(eve=em->verts.first; eve; eve= eve->next, evec++, a++) { for(eve=em->verts.first; eve; eve= eve->next, evec++, a++) {
VECCOPY(evec->co, eve->co); VECCOPY(evec->co, eve->co);
VECCOPY(evec->no, eve->no); VECCOPY(evec->no, eve->no);
@ -1664,12 +1664,12 @@ static void *editMesh_to_undoMesh(void)
evec->keyindex= eve->keyindex; evec->keyindex= eve->keyindex;
evec->totweight= eve->totweight; evec->totweight= eve->totweight;
evec->dw= MEM_dupallocN(eve->dw); evec->dw= MEM_dupallocN(eve->dw);
eve->tmp.l = a; /*store index*/
eve->tmp.l = a;
} }
/* copy edges */ /* copy edges */
for(eed=em->edges.first; eed; eed= eed->next, eedc++) { a = 0;
for(eed=em->edges.first; eed; eed= eed->next, eedc++, a++) {
eedc->v1= (int)eed->v1->tmp.l; eedc->v1= (int)eed->v1->tmp.l;
eedc->v2= (int)eed->v2->tmp.l; eedc->v2= (int)eed->v2->tmp.l;
eedc->f= eed->f; eedc->f= eed->f;
@ -1677,10 +1677,12 @@ static void *editMesh_to_undoMesh(void)
eedc->seam= eed->seam; eedc->seam= eed->seam;
eedc->crease= (short)(eed->crease*255.0); eedc->crease= (short)(eed->crease*255.0);
eedc->fgoni= eed->fgoni; eedc->fgoni= eed->fgoni;
eed->tmp.l = a; /*store index*/
} }
/* copy faces */ /* copy faces */
for(efa=em->faces.first; efa; efa= efa->next, efac++) { a = 0;
for(efa=em->faces.first; efa; efa= efa->next, efac++, a++) {
efac->v1= (int)efa->v1->tmp.l; efac->v1= (int)efa->v1->tmp.l;
efac->v2= (int)efa->v2->tmp.l; efac->v2= (int)efa->v2->tmp.l;
efac->v3= (int)efa->v3->tmp.l; efac->v3= (int)efa->v3->tmp.l;
@ -1697,6 +1699,15 @@ static void *editMesh_to_undoMesh(void)
*tface= efa->tf; *tface= efa->tf;
tface++; tface++;
} }
efa->tmp.l = a; /*store index*/
}
a = 0;
for(ese=em->selected.first; ese; ese=ese->next, esec++){
esec->type = ese->type;
if(ese->type == EDITVERT) a = esec->index = ((EditVert*)ese->data)->tmp.l;
else if(ese->type == EDITEDGE) a = esec->index = ((EditEdge*)ese->data)->tmp.l;
else if(ese->type == EDITFACE) a = esec->index = ((EditFace*)ese->data)->tmp.l;
} }
return um; return um;
@ -1709,9 +1720,11 @@ static void undoMesh_to_editMesh(void *umv)
EditVert *eve, **evar=NULL; EditVert *eve, **evar=NULL;
EditEdge *eed; EditEdge *eed;
EditFace *efa; EditFace *efa;
EditSelection *ese;
EditVertC *evec; EditVertC *evec;
EditEdgeC *eedc; EditEdgeC *eedc;
EditFaceC *efac; EditFaceC *efac;
EditSelectionC *esec;
TFace *tface; TFace *tface;
int a=0; int a=0;
@ -1774,21 +1787,22 @@ static void undoMesh_to_editMesh(void *umv)
end_editmesh_fastmalloc(); end_editmesh_fastmalloc();
if(evar) MEM_freeN(evar); if(evar) MEM_freeN(evar);
/*restore last and first selected vertex pointers*/ G.totvert = um->totvert;
G.totedge = um->totedge;
G.totvert = um->totvert; G.totface = um->totface;
if(um->lastvert != -1 || um-> firstvert != -1){ /*restore stored editselections*/
if(um->totsel){
EM_init_index_arrays(1,0,0); EM_init_index_arrays(1,1,1);
if(um->lastvert != -1) em->lastvert = EM_get_vert_for_index(um->lastvert); for(a=0, esec= um->selected; a<um->totsel; a++, esec++){
else em->lastvert = NULL; ese = MEM_callocN(sizeof(EditSelection), "Edit Selection");
ese->type = esec->type;
if(um->firstvert != -1) em->firstvert = EM_get_vert_for_index(um->firstvert); if(ese->type == EDITVERT) ese->data = EM_get_vert_for_index(esec->index); else
else em->firstvert = NULL; if(ese->type == EDITEDGE) ese->data = EM_get_edge_for_index(esec->index); else
if(ese->type == EDITFACE) ese->data = EM_get_face_for_index(esec->index);
BLI_addtail(&(em->selected),ese);
}
EM_free_index_arrays(); EM_free_index_arrays();
} }
} }

@ -67,7 +67,74 @@ editmesh_lib: generic (no UI, no menus) operations/evaluators for editmesh data
#include "editmesh.h" #include "editmesh.h"
//TODO
//fix undo code. Biggest one.
//fix issues with EM_selectmode_set()
//get rid of 'lastvert' and 'firstvert' hacks in EditMesh struct and clean from undo code and 'load_editmesh' code and elsewhere
//find out if storing EditSelection(s) in Mesh DNA is 'ok', even if only for runtime(?)
/* ********* Selection ************ */ /* ********* Selection ************ */
static int EM_check_selection(void *data)
{
EditSelection *ese;
for(ese = G.editMesh->selected.first; ese; ese = ese->next){
if(ese->data == data) return 1;
}
return 0;
}
void EM_remove_selection(void *data, int type)
{
EditSelection *ese;
for(ese=G.editMesh->selected.first; ese; ese = ese->next){
if(ese->data == data){
BLI_freelinkN(&(G.editMesh->selected),ese);
break;
}
}
}
void EM_store_selection(void *data, int type)
{
EditSelection *ese;
if(!EM_check_selection(data)){
ese = (EditSelection*) MEM_callocN( sizeof(EditSelection), "Edit Selection");
ese->type = type;
ese->data = data;
BLI_addtail(&(G.editMesh->selected),ese);
}
}
static void EM_strip_selections(void)
{
EditSelection *ese, *nextese;
if(!(G.scene->selectmode & SCE_SELECT_VERTEX)){
ese = G.editMesh->selected.first;
while(ese){
nextese = ese->next;
if(ese->type == EDITVERT) BLI_freelinkN(&(G.editMesh->selected),ese);
ese = nextese;
}
}
if(!(G.scene->selectmode & SCE_SELECT_EDGE)){
ese=G.editMesh->selected.first;
while(ese){
nextese = ese->next;
if(ese->type == EDITEDGE) BLI_freelinkN(&(G.editMesh->selected), ese);
ese = nextese;
}
}
if(!(G.scene->selectmode & SCE_SELECT_FACE)){
ese=G.editMesh->selected.first;
while(ese){
nextese = ese->next;
if(ese->type == EDITFACE) BLI_freelinkN(&(G.editMesh->selected), ese);
ese = nextese;
}
}
}
void EM_select_face(EditFace *efa, int sel) void EM_select_face(EditFace *efa, int sel)
{ {
@ -205,6 +272,7 @@ void EM_clear_flag_all(int flag)
for (eed= em->edges.first; eed; eed= eed->next) eed->f &= ~flag; for (eed= em->edges.first; eed; eed= eed->next) eed->f &= ~flag;
for (efa= em->faces.first; efa; efa= efa->next) efa->f &= ~flag; for (efa= em->faces.first; efa; efa= efa->next) efa->f &= ~flag;
if(flag & SELECT) BLI_freelistN(&(G.editMesh->selected));
} }
void EM_set_flag_all(int flag) void EM_set_flag_all(int flag)
@ -463,7 +531,8 @@ void EM_selectmode_set(void)
EditVert *eve; EditVert *eve;
EditEdge *eed; EditEdge *eed;
EditFace *efa; EditFace *efa;
EM_strip_selections(); /*strip EditSelections from em->selected that are not relevant to new mode*/
if(G.scene->selectmode == SCE_SELECT_VERTEX) { if(G.scene->selectmode == SCE_SELECT_VERTEX) {
/* vertices -> edges -> faces */ /* vertices -> edges -> faces */
for (eed= em->edges.first; eed; eed= eed->next) eed->f &= ~SELECT; for (eed= em->edges.first; eed; eed= eed->next) eed->f &= ~SELECT;
@ -478,7 +547,6 @@ void EM_selectmode_set(void)
if(eed->f & SELECT) EM_select_edge(eed, 1); if(eed->f & SELECT) EM_select_edge(eed, 1);
/* selects faces based on edge status */ /* selects faces based on edge status */
EM_selectmode_flush(); EM_selectmode_flush();
} }
else if(G.scene->selectmode == SCE_SELECT_FACE) { else if(G.scene->selectmode == SCE_SELECT_FACE) {
/* deselect eges, and select again based on face select */ /* deselect eges, and select again based on face select */

@ -1479,27 +1479,33 @@ void mouse_mesh(void)
if(efa) { if(efa) {
if( (efa->f & SELECT)==0 ) { if( (efa->f & SELECT)==0 ) {
EM_store_selection(efa, EDITFACE);
EM_select_face_fgon(efa, 1); EM_select_face_fgon(efa, 1);
} }
else if(G.qual & LR_SHIFTKEY) { else if(G.qual & LR_SHIFTKEY) {
EM_remove_selection(efa, EDITFACE);
EM_select_face_fgon(efa, 0); EM_select_face_fgon(efa, 0);
} }
} }
else if(eed) { else if(eed) {
if((eed->f & SELECT)==0) { if((eed->f & SELECT)==0) {
EM_store_selection(eed, EDITEDGE);
EM_select_edge(eed, 1); EM_select_edge(eed, 1);
} }
else if(G.qual & LR_SHIFTKEY) { else if(G.qual & LR_SHIFTKEY) {
EM_remove_selection(eed, EDITEDGE);
EM_select_edge(eed, 0); EM_select_edge(eed, 0);
} }
} }
else if(eve) { else if(eve) {
if((eve->f & SELECT)==0) { if((eve->f & SELECT)==0) {
eve->f |= SELECT; eve->f |= SELECT;
if((G.qual & LR_SHIFTKEY)==0) G.editMesh->firstvert = eve; EM_store_selection(eve, EDITVERT);
else G.editMesh->lastvert = eve; }
else if(G.qual & LR_SHIFTKEY){
EM_remove_selection(eve, EDITVERT);
eve->f &= ~SELECT;
} }
else if(G.qual & LR_SHIFTKEY) eve->f &= ~SELECT;
} }
/* frontbuffer draw of last selected only */ /* frontbuffer draw of last selected only */

@ -1071,6 +1071,7 @@ void delete_mesh(void)
if(em->verts.first) free_vertlist(&em->verts); if(em->verts.first) free_vertlist(&em->verts);
if(em->edges.first) free_edgelist(&em->edges); if(em->edges.first) free_edgelist(&em->edges);
if(em->faces.first) free_facelist(&em->faces); if(em->faces.first) free_facelist(&em->faces);
if(em->selected.first) BLI_freelistN(&(em->selected));
} }
else if(event==5) { else if(event==5) {
str= "Erase Only Faces"; str= "Erase Only Faces";
@ -6034,8 +6035,16 @@ int collapseFaces(int uvmerge){
int merge_firstlast(int first, int uvmerge) int merge_firstlast(int first, int uvmerge)
{ {
EditVert *eve,*mergevert; EditVert *eve,*mergevert;
if(first == 0) mergevert=G.editMesh->lastvert; EditSelection *ese;
else mergevert=G.editMesh->firstvert; /* do sanity check in mergemenu in edit.c ?*/
if(first == 0){
ese = G.editMesh->selected.last;
mergevert= (EditVert*)ese->data;
}
else{
ese = G.editMesh->selected.first;
mergevert = (EditVert*)ese->data;
}
if(mergevert->f&SELECT){ if(mergevert->f&SELECT){
for (eve=G.editMesh->verts.first; eve; eve=eve->next){ for (eve=G.editMesh->verts.first; eve; eve=eve->next){
@ -6095,6 +6104,7 @@ void pathselect(void)
{ {
EditVert *eve, *s, *t; EditVert *eve, *s, *t;
EditEdge *eed; EditEdge *eed;
EditSelection *ese;
PathEdge *newpe, *currpe; PathEdge *newpe, *currpe;
PathNode *currpn; PathNode *currpn;
PathNode *Q; PathNode *Q;
@ -6108,18 +6118,13 @@ void pathselect(void)
countall(); /*paranoid?*/ countall(); /*paranoid?*/
ese = ((EditSelection*)G.editMesh->selected.last);
if(G.totvertsel == 2 && G.totedgesel == 0){ if(ese && ese->type == EDITVERT && ese->prev && ese->prev->type == EDITVERT){
physical= pupmenu("Distance Method? %t|Edge Length%x1|Topological%x0"); physical= pupmenu("Distance Method? %t|Edge Length%x1|Topological%x0");
for(eve=G.editMesh->verts.first; eve; eve=eve->next){
if(t) break; t = (EditVert*)ese->data;
else{ s = (EditVert*)ese->prev->data;
if(eve->f&SELECT){
if(s) t = eve;
else s = eve;
}
}
}
/*need to find out if t is actually reachable by s....*/ /*need to find out if t is actually reachable by s....*/
for(eve=G.editMesh->verts.first; eve; eve=eve->next){ for(eve=G.editMesh->verts.first; eve; eve=eve->next){
eve->f1 = 0; eve->f1 = 0;
@ -6433,4 +6438,4 @@ void loop_to_region(void)
countall(); countall();
freecollections(&allcollections); freecollections(&allcollections);
BIF_undo_push("Edge Loop to Face Region"); BIF_undo_push("Edge Loop to Face Region");
} }