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
diff options
context:
space:
mode:
authorGeoffrey Bantle <hairbat@yahoo.com>2006-02-14 01:49:46 +0300
committerGeoffrey Bantle <hairbat@yahoo.com>2006-02-14 01:49:46 +0300
commit1f21e2eea708ee73491b508c29b159ae170fe713 (patch)
treea4a3e84cb6c88a13c3848f7692e94734d9c1cf3c
parent9104862f48b0caf3131f583a382fcce3b4b7c289 (diff)
Modified Files:
source/blender/blenlib/BLI_editVert.h source/blender/include/BIF_editmesh.h source/blender/src/edit.c source/blender/src/editmesh.c source/blender/src/editmesh_lib.c source/blender/src/editmesh_mods.c source/blender/src/editmesh_tools.c source/blender/src/header_view3d.c Log: Commit of the 'upgraded merge tools' (Patch #3345) and 'inclusive selection mode conversion' (Patch #3768).
-rw-r--r--source/blender/blenlib/BLI_editVert.h3
-rw-r--r--source/blender/include/BIF_editmesh.h4
-rw-r--r--source/blender/src/edit.c76
-rw-r--r--source/blender/src/editmesh.c47
-rw-r--r--source/blender/src/editmesh_lib.c65
-rw-r--r--source/blender/src/editmesh_mods.c20
-rw-r--r--source/blender/src/editmesh_tools.c379
-rw-r--r--source/blender/src/header_view3d.c18
8 files changed, 588 insertions, 24 deletions
diff --git a/source/blender/blenlib/BLI_editVert.h b/source/blender/blenlib/BLI_editVert.h
index 315498bab4c..57fe08e5305 100644
--- a/source/blender/blenlib/BLI_editVert.h
+++ b/source/blender/blenlib/BLI_editVert.h
@@ -130,6 +130,9 @@ typedef struct EditMesh
EditEdge *alledges, *curedge;
EditFace *allfaces, *curface;
+ /*for improved merge code*/
+ EditVert *lastvert, *firstvert;
+
/* DerivedMesh caches... note that derived cage can be equivalent
* to derived final, care should be taken on release.
*/
diff --git a/source/blender/include/BIF_editmesh.h b/source/blender/include/BIF_editmesh.h
index b1620ec58a6..8c5fa1660ce 100644
--- a/source/blender/include/BIF_editmesh.h
+++ b/source/blender/include/BIF_editmesh.h
@@ -202,5 +202,9 @@ int editface_containsEdge(struct EditFace *efa, struct EditEdge *eed);
void shape_copy_select_from(void);
void shape_propagate(void);
+int collapseEdges(void);
+int collapseFaces(void);
+int merge_firstlast(int first);
+
#endif
diff --git a/source/blender/src/edit.c b/source/blender/src/edit.c
index 355aee6e6c9..6ee71832651 100644
--- a/source/blender/src/edit.c
+++ b/source/blender/src/edit.c
@@ -66,6 +66,7 @@
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
#include "BLI_editVert.h"
+#include "BLI_linklist.h"
#include "BKE_action.h"
#include "BKE_armature.h"
@@ -600,6 +601,17 @@ void countall()
G.totface++;
if(efa->f & SELECT) G.totfacesel++;
}
+
+ /*for keeping track of last & first vertex selected*/
+ /*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){
for (ebo=G.edbo.first;ebo;ebo=ebo->next){
@@ -1552,25 +1564,61 @@ void snapmenu()
}
+#define MERGELIMIT 0.001
void mergemenu(void)
-{
- short event;
-
- event = pupmenu("Merge %t|At Center%x1|At Cursor%x2");
-
- if (event==-1) return; /* Return if the menu is closed without any choices */
-
- if (event==1)
- snap_to_center(); /*Merge at Center*/
- else
- snap_sel_to_curs(); /*Merge at Cursor*/
+{
- notice("Removed %d Vertices", removedoublesflag(1, G.scene->toolsettings->doublimit));
+ short event;
+ int remCount;
+ 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");
+ else if (G.editMesh->firstvert) event = pupmenu("Merge %t|At First %x6|At Center%x3|At Cursor%x4");
+ else if (G.editMesh->lastvert) 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 if(G.scene->selectmode == SCE_SELECT_EDGE)
+ event = pupmenu("Merge %t|Collapse Edges%x2|At Center%x3|At Cursor%x4");
+
+ else if(G.scene->selectmode == SCE_SELECT_FACE)
+ event = pupmenu("Merge %t|Collapse Faces%x5|At Center%x3|At Cursor%x4");
+ else event = pupmenu("Merge %t|At Center%x3|At Cursor%x4");
+ switch (event)
+ {
+ case -1:
+ return;
+ case 3:
+ snap_to_center();
+ remCount = removedoublesflag(1,MERGELIMIT);
+ BIF_undo_push("Merge at center");
+ break;
+ case 4:
+ snap_sel_to_curs();
+ remCount = removedoublesflag(1,MERGELIMIT);
+ BIF_undo_push("Merge at cursor");
+ break;
+ case 1:
+ remCount = merge_firstlast(0);
+ BIF_undo_push("Merge at last selected");
+ break;
+ case 6:
+ remCount = merge_firstlast(1);
+ BIF_undo_push("Merge at first selected");
+ break;
+ case 2:
+ remCount = collapseEdges();
+ BIF_undo_push("Collapse Edges");
+ break;
+ case 5:
+ remCount = collapseFaces();
+ BIF_undo_push("Collapse Faces");
+ break;
+ }
+ notice("Removed %d Vertices", remCount);
allqueue(REDRAWVIEW3D, 0);
countall();
- BIF_undo_push("Merge"); /* push the mesh down the undo pipe */
-
}
+#undef MERGELIMIT
+
void delete_context_selected(void)
{
diff --git a/source/blender/src/editmesh.c b/source/blender/src/editmesh.c
index e54bb0c156d..fefec0b460d 100644
--- a/source/blender/src/editmesh.c
+++ b/source/blender/src/editmesh.c
@@ -1575,6 +1575,8 @@ typedef struct UndoMesh {
EditFaceC *faces;
TFace *tfaces;
int totvert, totedge, totface;
+ int lastvert, firstvert; /*index for last and first selected vert. -1 if no first/last vert exists (nasty)*/
+ short selectmode;
} UndoMesh;
@@ -1609,9 +1611,30 @@ static void *editMesh_to_undoMesh(void)
EditEdgeC *eedc=NULL;
EditFaceC *efac=NULL;
TFace *tface= NULL;
- int a=0;
+ int i, a=0;
um= MEM_callocN(sizeof(UndoMesh), "undomesh");
+
+ 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(eed=em->edges.first; eed; eed= eed->next) um->totedge++;
@@ -1678,7 +1701,7 @@ static void *editMesh_to_undoMesh(void)
static void undoMesh_to_editMesh(void *umv)
{
- UndoMesh *um= umv;
+ UndoMesh *um= (UndoMesh*)umv;
EditMesh *em= G.editMesh;
EditVert *eve, **evar=NULL;
EditEdge *eed;
@@ -1689,11 +1712,15 @@ static void undoMesh_to_editMesh(void *umv)
TFace *tface;
int a=0;
+ G.scene->selectmode = um->selectmode;
+
free_editMesh(G.editMesh);
/* malloc blocks */
memset(em, 0, sizeof(EditMesh));
+
+
init_editmesh_fastmalloc(em, um->totvert, um->totedge, um->totface);
/* now copy vertices */
@@ -1743,6 +1770,22 @@ static void undoMesh_to_editMesh(void *umv)
end_editmesh_fastmalloc();
if(evar) MEM_freeN(evar);
+
+ /*restore last and first selected vertex pointers*/
+
+ G.totvert = um->totvert;
+ if(um->lastvert != -1 || um-> firstvert != -1){
+
+ EM_init_index_arrays(1,0,0);
+ if(um->lastvert != -1) em->lastvert = EM_get_vert_for_index(um->lastvert);
+ else em->lastvert = NULL;
+
+ if(um->firstvert != -1) em->firstvert = EM_get_vert_for_index(um->firstvert);
+ else em->firstvert = NULL;
+
+ EM_free_index_arrays();
+ }
+
}
diff --git a/source/blender/src/editmesh_lib.c b/source/blender/src/editmesh_lib.c
index fecd6efecce..8c57120021b 100644
--- a/source/blender/src/editmesh_lib.c
+++ b/source/blender/src/editmesh_lib.c
@@ -392,6 +392,70 @@ void EM_selectmode_flush(void)
}
+void EM_convertsel(short oldmode, short selectmode)
+{
+ EditMesh *em = G.editMesh;
+ EditVert *eve;
+ EditEdge *eed;
+ EditFace *efa;
+ /*clear flags*/
+ for(eve= em->verts.first; eve; eve= eve->next) eve->f1 = 0;
+ for(eed= em->edges.first; eed; eed= eed->next) eed->f1 = 0;
+ for(efa= em->faces.first; efa; efa= efa->next) efa->f1 = 0;
+
+ /*have to find out what the selectionmode was previously*/
+ if(oldmode == SCE_SELECT_VERTEX) {
+ if(selectmode == SCE_SELECT_EDGE){
+ /*select all edges associated with every selected vertex*/
+ for(eed= em->edges.first; eed; eed= eed->next){
+ if(eed->v1->f&SELECT) eed->f1 = 1;
+ else if(eed->v2->f&SELECT) eed->f1 = 1;
+ }
+
+ for(eed= em->edges.first; eed; eed= eed->next){
+ if(eed->f1 == 1) EM_select_edge(eed,1);
+ }
+ }
+ else if(selectmode == SCE_SELECT_FACE){
+ /*select all faces associated with every selected vertex*/
+ for(efa= em->faces.first; efa; efa= efa->next){
+ if(efa->v1->f&SELECT) efa->f1 = 1;
+ else if(efa->v2->f&SELECT) efa->f1 = 1;
+ else if(efa->v3->f&SELECT) efa->f1 = 1;
+ else{
+ if(efa->v4){
+ if(efa->v4->f&SELECT) efa->f1 =1;
+ }
+ }
+
+ }
+ for(efa= em->faces.first; efa; efa= efa->next){
+ if(efa->f1 == 1) EM_select_face(efa,1);
+ }
+ check_fgons_selection();
+ countall();
+ }
+ }
+
+ if(oldmode == SCE_SELECT_EDGE){
+ if(selectmode == SCE_SELECT_FACE){
+ for(efa= em->faces.first; efa; efa= efa->next){
+ if(efa->e1->f&SELECT) efa->f1 = 1;
+ else if(efa->e2->f&SELECT) efa->f1 = 1;
+ else if(efa->e3->f&SELECT) efa->f1 = 1;
+ else if(efa->e4){
+ if(efa->e4->f&SELECT) efa->f1 = 1;
+ }
+ }
+ for(efa= em->faces.first; efa; efa= efa->next){
+ if(efa->f1 == 1) EM_select_face(efa,1);
+ }
+ check_fgons_selection();
+ countall();
+ }
+ }
+}
+
/* when switching select mode, makes sure selection is consistant for editing */
/* also for paranoia checks to make sure edge or face mode works */
void EM_selectmode_set(void)
@@ -424,6 +488,7 @@ void EM_selectmode_set(void)
for(efa= em->faces.first; efa; efa= efa->next)
if(efa->f & SELECT) EM_select_face(efa, 1);
}
+ BIF_undo_push("Selectmode Set");
}
/* paranoia check, actually only for entering editmode. rule:
diff --git a/source/blender/src/editmesh_mods.c b/source/blender/src/editmesh_mods.c
index aa3353046a8..7179543c695 100644
--- a/source/blender/src/editmesh_mods.c
+++ b/source/blender/src/editmesh_mods.c
@@ -1052,7 +1052,11 @@ void mouse_mesh(void)
}
}
else if(eve) {
- if((eve->f & SELECT)==0) eve->f |= SELECT;
+ if((eve->f & SELECT)==0) {
+ eve->f |= SELECT;
+ if((G.qual & LR_SHIFTKEY)==0) G.editMesh->firstvert = eve;
+ else G.editMesh->lastvert = eve;
+ }
else if(G.qual & LR_SHIFTKEY) eve->f &= ~SELECT;
}
@@ -1937,10 +1941,20 @@ void EM_selectmode_menu(void)
else pupmenu_set_active(3);
val= pupmenu("Select Mode%t|Vertices|Edges|Faces");
+
+
if(val>0) {
if(val==1) G.scene->selectmode= SCE_SELECT_VERTEX;
- else if(val==2) G.scene->selectmode= SCE_SELECT_EDGE;
- else G.scene->selectmode= SCE_SELECT_FACE;
+
+ else if(val==2){
+ if((G.qual==LR_CTRLKEY)) EM_convertsel(G.scene->selectmode, SCE_SELECT_EDGE);
+ G.scene->selectmode= SCE_SELECT_EDGE;
+ }
+
+ else{
+ if((G.qual==LR_CTRLKEY)) EM_convertsel(G.scene->selectmode, SCE_SELECT_FACE);
+ G.scene->selectmode= SCE_SELECT_FACE;
+ }
EM_selectmode_set(); // when mode changes
allqueue(REDRAWVIEW3D, 1);
diff --git a/source/blender/src/editmesh_tools.c b/source/blender/src/editmesh_tools.c
index c244f1d249c..3bc528e7702 100644
--- a/source/blender/src/editmesh_tools.c
+++ b/source/blender/src/editmesh_tools.c
@@ -5565,4 +5565,383 @@ void shape_copy_select_from()
return;
}
+/* Collection Routines|Currently used by the improved merge code*/
+/* both buildEdge_collection() and buildFace_collection() create a series of lists*/
+/* these lists are filled with edges or faces that are topologically connected.*/
+
+#define MERGELIMIT 0.001
+
+LinkNode *build_edgecollection(LinkNode *allCollections)
+{
+ EditEdge *eed;
+
+ LinkNode *edgeCollection, *currEdge;
+
+ edgeCollection = NULL;
+ currEdge = NULL;
+ allCollections = NULL;
+
+ int currTag, lowtag;
+
+ short ebalanced = 0;
+ short listfound;
+
+ currTag = 1;
+
+ for (eed=G.editMesh->edges.first; eed; eed = eed->next)
+ {
+ eed->tmp.l = 0;
+ eed->v1->tmp.l = 0;
+ eed->v2->tmp.l = 0;
+ }
+
+ /*1st pass*/
+ for(eed=G.editMesh->edges.first; eed; eed=eed->next)
+ {
+ if(eed->f&SELECT)
+ {
+
+ eed->v1->tmp.l = currTag;
+ eed->v2->tmp.l = currTag;
+
+ currTag +=1;
+ }
+ }
+
+ /*2nd pass - Brute force. Loop through selected faces until there are no 'unbalanced' edges left (those with both vertices 'tmp.l' tag matching */
+ while(ebalanced == 0)
+ {
+ ebalanced = 1;
+ for(eed=G.editMesh->edges.first; eed; eed = eed->next)
+ {
+ if(eed->f&SELECT)
+ {
+ if(eed->v1->tmp.l != eed->v2->tmp.l) /*unbalanced*/
+ {
+ if(eed->v1->tmp.l > eed->v2->tmp.l && eed->v2->tmp.l !=0) eed->v1->tmp.l = eed->v2->tmp.l;
+ else if(eed->v1 != 0) eed->v2->tmp.l = eed->v1->tmp.l;
+ ebalanced = 0;
+ }
+ }
+ }
+ }
+
+ /*3rd pass, set all the edge flags (unnessecary?)*/
+ for(eed=G.editMesh->edges.first; eed; eed = eed->next)
+ {
+ if(eed->f&SELECT) eed->tmp.l = eed->v1->tmp.l;
+ }
+
+ /*build our list of lists - Needs to be in a seperate function, identical to build_facecollection()!*/
+ for(eed=G.editMesh->edges.first; eed; eed=eed->next)
+ {
+ if(eed->f&SELECT)
+ {
+ if(allCollections) /*allCollections is NOT NULL*/
+ {
+ for(edgeCollection = allCollections; edgeCollection; edgeCollection=edgeCollection->next)
+ {
+ currEdge = edgeCollection->link;
+ if(((EditEdge*)currEdge->link)->tmp.l == eed->tmp.l)
+ {
+ BLI_linklist_append(&currEdge,eed);
+ listfound = 1;
+ break;
+ }
+ else listfound = 0;
+ }
+
+ if(!listfound)
+ {
+ /*add a new faceCollection to the Collections list*/
+ edgeCollection = NULL;
+ BLI_linklist_prepend(&edgeCollection, eed);
+ BLI_linklist_append(allCollections, edgeCollection);
+
+ }
+ }
+ else /*allCollections is a 'zero length list'*/
+ {
+ edgeCollection = NULL;
+ BLI_linklist_prepend(&edgeCollection, eed);
+ BLI_linklist_prepend(&allCollections, edgeCollection); /*this actually looks like it is correct*/
+ }
+ }
+ }
+ return allCollections;
+
+}
+
+LinkNode *build_facecollection(LinkNode *allCollections) /*Builds a collection of lists of connected faces from the currently selected set*/
+{
+ EditFace *efa;
+
+ LinkNode *faceCollection, *currFace;
+
+ faceCollection = NULL;
+ currFace = NULL;
+ allCollections = NULL;
+
+ int currTag, lowtag;
+ short listfound,aCount;
+ int tagArray[3]; /*used to pull the tags out of faces vertices. an entry of -1 means no vertex exists....*/
+ currTag = 1; /*don't start with zero since f1 is cleared to that in editvert and editface structs already*/
+
+ for (efa=G.editMesh->faces.first; efa; efa=efa->next){
+
+ efa->tmp.l = 0;
+ efa->v1->tmp.l = 0;
+ efa->v2->tmp.l = 0;
+ efa->v3->tmp.l = 0;
+ if(efa->v4) efa->v4->tmp.l = 0;
+
+ }
+
+ /*1st pass*/
+ for (efa=G.editMesh->faces.first; efa; efa=efa->next)
+ {
+
+ if(efa->f&SELECT)
+ { /*face has no vertices that have been visited before since all the f1 tags are zero*/
+ if((efa->v1->tmp.l + efa->v2->tmp.l + efa->v3->tmp.l + ((efa->v4) ? efa->v4->tmp.l : 0)) == 0)
+ {
+ efa->v1->tmp.l = currTag;
+ efa->v2->tmp.l = currTag;
+ efa->v3->tmp.l = currTag;
+ if(efa->v4) efa->v4->tmp.l = currTag;
+ }
+ else
+ { /*the face has some vert tagged allready as a result of another face that it shares verts with being already visited*/
+ lowtag = currTag+1; /* plus one? why? this makes little sense!*/
+
+ /*test to find the lowest tag....*/
+ if(efa->v1->tmp.l < lowtag && efa->v1->tmp.l != 0 && efa->v1->tmp.l != -1) lowtag = efa->v1->tmp.l;
+ if(efa->v2->tmp.l < lowtag && efa->v2->tmp.l != 0 && efa->v2->tmp.l != -1) lowtag = efa->v2->tmp.l;
+ if(efa->v3->tmp.l < lowtag && efa->v3->tmp.l != 0 && efa->v3->tmp.l != -1) lowtag = efa->v3->tmp.l;
+
+ if(efa->v4){
+ if(efa->v4->tmp.l < lowtag && efa->v4->tmp.l != 0 && efa->v4->tmp.l != -1) lowtag = efa->v4->tmp.l;
+ }
+
+ /*set all vertices to lowest tag*/
+ efa->v1->tmp.l = lowtag;
+ efa->v2->tmp.l = lowtag;
+ efa->v3->tmp.l = lowtag;
+ if(efa->v4) efa->v4->tmp.l = lowtag;
+ }
+ currTag += 1;
+ }
+ }
+
+ /*2nd pass - Nessecary because of faces connected only by a single vertex*/
+
+ for (efa=G.editMesh->faces.first; efa; efa=efa->next)
+ {
+
+ lowtag = currTag+1; /*plus one? why? this makes little sense!*/
+ if(efa->f&SELECT)
+ {
+ tagArray[0] = efa->v1->tmp.l;
+ tagArray[1] = efa->v2->tmp.l;
+ tagArray[2] = efa->v3->tmp.l;
+ tagArray[3] = (efa->v4) ? efa->v4->tmp.l : -1; /*could be a triangle, have to test*/
+
+ if(efa->v1->tmp.l < lowtag && efa->v1->tmp.l != 0 && efa->v1->tmp.l != -1) lowtag = efa->v1->tmp.l;
+ if(efa->v2->tmp.l < lowtag && efa->v2->tmp.l != 0 && efa->v2->tmp.l != -1) lowtag = efa->v2->tmp.l;
+ if(efa->v3->tmp.l < lowtag && efa->v3->tmp.l != 0 && efa->v3->tmp.l != -1) lowtag = efa->v3->tmp.l;
+
+ if(efa->v4){
+ if(efa->v4->tmp.l < lowtag && efa->v4->tmp.l != 0 && efa->v4->tmp.l != -1) lowtag = efa->v4->tmp.l;
+ }
+
+
+ efa->tmp.l = lowtag; /*actually tag the face now with lowtag*/
+ }
+ }
+
+ /*build our list of lists*/
+ for(efa=G.editMesh->faces.first; efa; efa=efa->next)
+ {
+ if(efa->f&SELECT)
+ {
+ if(allCollections) /*allCollections is NOT NULL*/
+ {
+ for(faceCollection = allCollections; faceCollection; faceCollection=faceCollection->next)
+ {
+ currFace = faceCollection->link;
+ if(((EditFace*)currFace->link)->tmp.l == efa->tmp.l) /*put efa into this list.........*/
+ {
+ BLI_linklist_append(&currFace,efa);
+ listfound = 1;
+ break;
+ }
+ else listfound = 0;
+ }
+
+ if(!listfound)
+ {
+ /*add a new faceCollection to the Collections list*/
+ faceCollection = NULL;
+ BLI_linklist_prepend(&faceCollection, efa);
+ BLI_linklist_append(allCollections, faceCollection);
+
+ }
+ }
+ else /*allCollections is a 'zero length list'*/
+ {
+ faceCollection = NULL;
+ BLI_linklist_prepend(&faceCollection, efa);
+ BLI_linklist_prepend(&allCollections, faceCollection); /*this actually looks like it is correct*/
+ }
+ }
+ }
+ return allCollections;
+ }
+
+void freeCollections(LinkNode *allCollections)
+{
+ LinkNode *Collection;
+ Collection = NULL;
+
+ for(Collection = allCollections; Collection; Collection = Collection->next)
+ {
+ BLI_linklist_free((LinkNode*)Collection->link,NULL);
+ }
+
+ BLI_linklist_free(allCollections,NULL);
+}
+
+int collapseEdges(void)
+{
+ LinkNode *allCollections, *edgeCollection, *currEdge;
+
+ int totEdges, groupCount, mergecount,vCount;
+ float avgCount[3];
+
+ mergecount = 0;
+
+ allCollections = build_edgecollection(allCollections);
+ groupCount = BLI_linklist_length(allCollections);
+
+
+ for(edgeCollection = allCollections; edgeCollection; edgeCollection = edgeCollection->next)
+ {
+ totEdges = BLI_linklist_length(edgeCollection->link);
+ mergecount += totEdges;
+ avgCount[0] = 0; avgCount[1] = 0; avgCount[2] = 0;
+ vCount = 0;
+
+ for(currEdge = edgeCollection->link; currEdge; currEdge = currEdge->next)
+ {
+ avgCount[0] += ((EditEdge*)currEdge->link)->v1->co[0];
+ avgCount[1] += ((EditEdge*)currEdge->link)->v1->co[1];
+ avgCount[2] += ((EditEdge*)currEdge->link)->v1->co[2];
+
+ avgCount[0] += ((EditEdge*)currEdge->link)->v2->co[0];
+ avgCount[1] += ((EditEdge*)currEdge->link)->v2->co[1];
+ avgCount[2] += ((EditEdge*)currEdge->link)->v2->co[2];
+
+ vCount +=2;
+ }
+
+ avgCount[0] /= vCount; avgCount[1] /=vCount; avgCount[2] /= vCount;
+
+ for(currEdge = edgeCollection->link; currEdge; currEdge = currEdge->next)
+ {
+ VECCOPY(((EditEdge*)currEdge->link)->v1->co,avgCount);
+ VECCOPY(((EditEdge*)currEdge->link)->v2->co,avgCount);
+ }
+ }
+ freeCollections(allCollections);
+ removedoublesflag(1, MERGELIMIT);
+ /*get rid of this!*/
+ countall();
+ return mergecount;
+
+
+}
+
+int collapseFaces(void)
+{
+ LinkNode *allCollections, *faceCollection, *currFace;
+
+ int groupCount;
+ int vCount,totFaces,mergecount;
+ float avgCount[3];
+
+ mergecount = 0;
+ allCollections = build_facecollection(allCollections);
+ groupCount = BLI_linklist_length(allCollections);
+
+ for(faceCollection = allCollections; faceCollection; faceCollection = faceCollection->next)
+ {
+ totFaces = BLI_linklist_length(faceCollection->link);
+ mergecount += totFaces;
+ avgCount[0] = 0; avgCount[1] = 0; avgCount[2] = 0;
+ vCount = 0;
+ for(currFace = faceCollection->link; currFace; currFace = currFace->next)
+ {
+ avgCount[0] += ((EditFace*)currFace->link)->v1->co[0];
+ avgCount[1] += ((EditFace*)currFace->link)->v1->co[1];
+ avgCount[2] += ((EditFace*)currFace->link)->v1->co[2];
+
+ avgCount[0] += ((EditFace*)currFace->link)->v2->co[0];
+ avgCount[1] += ((EditFace*)currFace->link)->v2->co[1];
+ avgCount[2] += ((EditFace*)currFace->link)->v2->co[2];
+
+ avgCount[0] += ((EditFace*)currFace->link)->v3->co[0];
+ avgCount[1] += ((EditFace*)currFace->link)->v3->co[1];
+ avgCount[2] += ((EditFace*)currFace->link)->v3->co[2];
+
+ vCount+= 3;
+
+ if(((EditFace*)currFace->link)->v4)
+ {
+ avgCount[0] += ((EditFace*)currFace->link)->v3->co[0];
+ avgCount[1] += ((EditFace*)currFace->link)->v3->co[1];
+ avgCount[2] += ((EditFace*)currFace->link)->v3->co[2];
+ vCount+=1;
+ }
+
+ }
+
+ avgCount[0] /= vCount; avgCount[1] /=vCount; avgCount[2] /= vCount;
+
+ for(currFace = faceCollection->link; currFace; currFace = currFace->next)
+ {
+ VECCOPY(((EditFace*)currFace->link)->v1->co,avgCount);
+ VECCOPY(((EditFace*)currFace->link)->v2->co,avgCount);
+ VECCOPY(((EditFace*)currFace->link)->v3->co,avgCount);
+ if(((EditFace*)currFace->link)->v4) VECCOPY(((EditFace*)currFace->link)->v4->co, avgCount);
+ }
+ }
+ freeCollections(allCollections);
+ removedoublesflag(1, MERGELIMIT);
+ /*get rid of this!*/
+ countall();
+ return mergecount;
+}
+
+int merge_firstlast(int first)
+{
+ EditVert *ev,*mergevert;
+
+ if(first == 0) mergevert=G.editMesh->lastvert;
+ else mergevert=G.editMesh->firstvert;
+
+ if(mergevert->f&SELECT){
+ for (ev=G.editMesh->verts.first; ev; ev=ev->next)
+ {
+ if (ev->f&SELECT)
+ VECCOPY(ev->co,mergevert->co);
+ }
+ }
+
+ countall();
+
+return removedoublesflag(1,MERGELIMIT);
+}
+#undef MERGELIMIT
+
+
diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c
index a1120e9ed5d..03788e848f7 100644
--- a/source/blender/src/header_view3d.c
+++ b/source/blender/src/header_view3d.c
@@ -4093,17 +4093,25 @@ void do_view3d_buttons(short event)
allqueue(REDRAWVIEW3D, 1);
break;
case B_SEL_EDGE:
- if( (G.qual & LR_SHIFTKEY)==0 || G.scene->selectmode==0)
- G.scene->selectmode= SCE_SELECT_EDGE;
+ if( (G.qual & LR_SHIFTKEY)==0 || G.scene->selectmode==0){
+ if( (G.scene->selectmode ^ SCE_SELECT_EDGE) == SCE_SELECT_VERTEX){
+ if(G.qual==LR_CTRLKEY) EM_convertsel(SCE_SELECT_VERTEX,SCE_SELECT_EDGE);
+ }
+ G.scene->selectmode = SCE_SELECT_EDGE;
+ }
EM_selectmode_set();
allqueue(REDRAWVIEW3D, 1);
break;
case B_SEL_FACE:
- if( (G.qual & LR_SHIFTKEY)==0 || G.scene->selectmode==0)
- G.scene->selectmode= SCE_SELECT_FACE;
+ if( (G.qual & LR_SHIFTKEY)==0 || G.scene->selectmode==0){
+ if( ((G.scene->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_VERTEX) || ((G.scene->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_EDGE)){
+ if(G.qual==LR_CTRLKEY) EM_convertsel((G.scene->selectmode ^ SCE_SELECT_FACE),SCE_SELECT_FACE);
+ }
+ G.scene->selectmode = SCE_SELECT_FACE;
+ }
EM_selectmode_set();
allqueue(REDRAWVIEW3D, 1);
- break;
+ break;
case B_MAN_TRANS:
if( (G.qual & LR_SHIFTKEY)==0 || G.vd->twtype==0)