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).
This commit is contained in:
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
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");
|
||||
|
||||
event = pupmenu("Merge %t|At Center%x1|At Cursor%x2");
|
||||
else if(G.scene->selectmode == SCE_SELECT_EDGE)
|
||||
event = pupmenu("Merge %t|Collapse Edges%x2|At Center%x3|At Cursor%x4");
|
||||
|
||||
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));
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -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,10 +1611,31 @@ 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++;
|
||||
for(efa=em->faces.first; efa; efa= efa->next) um->totface++;
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4093,14 +4093,22 @@ 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;
|
||||
|
||||
Reference in New Issue
Block a user