diff --git a/source/blender/include/editmesh.h b/source/blender/include/editmesh.h index fb28bc24e19..4d40133317b 100644 --- a/source/blender/include/editmesh.h +++ b/source/blender/include/editmesh.h @@ -72,6 +72,9 @@ extern EditFace *exist_face(EditVert *v1, EditVert *v2, EditVert *v3, EditVert * extern void flipface(EditFace *efa); // flips for normal direction extern int compareface(EditFace *vl1, EditFace *vl2); +extern short extrudeflag_face_indiv(short flag); +extern short extrudeflag_verts_indiv(short flag); +extern short extrudeflag_edges_indiv(short flag); extern short extrudeflag_vert(short flag); extern short extrudeflag(short flag); diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c index 3903354f59b..bee80ee6b13 100644 --- a/source/blender/src/buttons_shading.c +++ b/source/blender/src/buttons_shading.c @@ -1199,7 +1199,7 @@ static void texture_panel_image(Tex *tex) uiDefButS(block, MENU, B_TEXIMABROWSE, strp, 10,135,23,20, &(G.buts->menunr), 0, 0, 0, 0, "Selects an existing texture or creates new"); if(tex->ima) { - uiDefBut(block, TEX, B_NAMEIMA, "", 35,135,255,20, tex->ima->name, 0.0, 79.0, 0, 0, "Displays name of the texture block: click to change"); + uiDefBut(block, TEX, B_NAMEIMA, "", 35,135,255,20, tex->ima->name, 0.0, 79.0, 0, 0, "Displays name of the Image file: click to change"); sprintf(str, "%d", tex->ima->id.us); uiDefBut(block, BUT, 0, str, 290,135,20,20, 0, 0, 0, 0, 0, "Displays number of users of texture: click to make single user"); uiBlockEndAlign(block); diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index cc1a6c7e792..d4e31e1a288 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -2544,10 +2544,12 @@ static void drawmeshwire_wirextra(DispListMesh *dlm, int optimal, char alpha) } else { /* draw faces twice, to have selected ones on top */ + /* we draw unselected the edges though, so they show in face mode */ glColor4ubv(wire); - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->h==0 && (efa->f & SELECT)==0) { - glVertex_efa_edges(efa); + for(eed= em->edges.first; eed; eed= eed->next) { + if(eed->h==0) { + glVertex3fv(eed->v1->co); + glVertex3fv(eed->v2->co); } } glColor4ubv(sel); diff --git a/source/blender/src/editmesh_lib.c b/source/blender/src/editmesh_lib.c index 7411be0ffbe..c3f7a069de7 100644 --- a/source/blender/src/editmesh_lib.c +++ b/source/blender/src/editmesh_lib.c @@ -460,6 +460,176 @@ static void set_edge_directions(void) } } +/* individual face extrude */ +short extrudeflag_face_indiv(short flag) +{ + EditMesh *em = G.editMesh; + EditVert *eve, *v1, *v2, *v3, *v4; + EditEdge *eed; + EditFace *efa, *nextfa; + + if(G.obedit==0 || get_mesh(G.obedit)==0) return 0; + + /* selected edges with 1 or more selected face become faces */ + /* selected faces each makes new faces */ + /* always remove old faces, keeps volumes manifold */ + /* select the new extrusion, deselect old */ + + /* step 1; init, count faces in edges */ + recalc_editnormals(); + + for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0; // new select flag + + for(eed= em->edges.first; eed; eed= eed->next) { + eed->f2= 0; // amount of unselected faces + } + for(efa= em->faces.first; efa; efa= efa->next) { + if(efa->f & SELECT); + else { + efa->e1->f2++; + efa->e2->f2++; + efa->e3->f2++; + if(efa->e4) efa->e4->f2++; + } + } + + /* step 2: make new faces from faces */ + for(efa= em->faces.last; efa; efa= efa->prev) { + if(efa->f & SELECT) { + v1= addvertlist(efa->v1->co); + v2= addvertlist(efa->v2->co); + v3= addvertlist(efa->v3->co); + v1->f1= v2->f1= v3->f1= 1; + VECCOPY(v1->no, efa->n); + VECCOPY(v2->no, efa->n); + VECCOPY(v3->no, efa->n); + if(efa->v4) { + v4= addvertlist(efa->v4->co); + v4->f1= 1; + VECCOPY(v4->no, efa->n); + } + else v4= NULL; + + /* side faces, clockwise */ + addfacelist(efa->v2, v2, v1, efa->v1, efa, NULL); + addfacelist(efa->v3, v3, v2, efa->v2, efa, NULL); + if(efa->v4) { + addfacelist(efa->v4, v4, v3, efa->v3, efa, NULL); + addfacelist(efa->v1, v1, v4, efa->v4, efa, NULL); + } + else { + addfacelist(efa->v1, v1, v3, efa->v3, efa, NULL); + } + /* top face */ + addfacelist(v1, v2, v3, v4, efa, NULL); + } + } + + /* step 3: remove old faces */ + efa= em->faces.first; + while(efa) { + nextfa= efa->next; + if(efa->f & SELECT) { + BLI_remlink(&em->faces, efa); + free_editface(efa); + } + efa= nextfa; + } + + /* step 4: redo selection */ + EM_clear_flag_all(SELECT); + + for(eve= em->verts.first; eve; eve= eve->next) { + if(eve->f1) eve->f |= SELECT; + } + + EM_select_flush(); + + return 'n'; +} + + +/* extrudes individual edges */ +short extrudeflag_edges_indiv(short flag) +{ + EditMesh *em = G.editMesh; + EditVert *eve; + EditEdge *eed; + EditFace *efa; + float nor[3]={0.0, 0.0, 0.0}; + + for(eve= em->verts.first; eve; eve= eve->next) eve->vn= NULL; + + set_edge_directions(); + + /* sample for next loop */ + for(efa= em->faces.first; efa; efa= efa->next) { + efa->e1->vn= (EditVert *)efa; + efa->e2->vn= (EditVert *)efa; + efa->e3->vn= (EditVert *)efa; + if(efa->e4) efa->e4->vn= (EditVert *)efa; + } + /* make the faces */ + for(eed= em->edges.first; eed; eed= eed->next) { + if(eed->f & flag) { + if(eed->v1->vn==NULL) eed->v1->vn= addvertlist(eed->v1->co); + if(eed->v2->vn==NULL) eed->v2->vn= addvertlist(eed->v2->co); + + if(eed->dir==1) addfacelist(eed->v1, eed->v2, eed->v2->vn, eed->v1->vn, (EditFace *)eed->vn, NULL); + else addfacelist(eed->v2, eed->v1, eed->v1->vn, eed->v2->vn, (EditFace *)eed->vn, NULL); + + /* for transform */ + if(eed->vn) { + efa= (EditFace *)eed->vn; + if(efa->f & SELECT) VecAddf(nor, nor, efa->n); + } + } + } + Normalise(nor); + + /* set correct selection */ + EM_clear_flag_all(SELECT); + for(eve= em->verts.last; eve; eve= eve->prev) { + if(eve->vn) { + eve->vn->f |= flag; + VECCOPY(eve->vn->no, nor); // transform() uses it + } + } + + for(eed= em->edges.first; eed; eed= eed->next) { + if(eed->v1->f & eed->v2->f & flag) eed->f |= flag; + } + + if(nor[0]==0.0 && nor[1]==0.0 && nor[2]==0.0) return 'g'; + return 'n'; +} + +/* extrudes individual vertices */ +short extrudeflag_verts_indiv(short flag) +{ + EditMesh *em = G.editMesh; + EditVert *eve; + + /* make the edges */ + for(eve= em->verts.first; eve; eve= eve->next) { + if(eve->f & flag) { + eve->vn= addvertlist(eve->co); + addedgelist(eve, eve->vn, NULL); + } + else eve->vn= NULL; + } + + /* set correct selection */ + EM_clear_flag_all(SELECT); + + for(eve= em->verts.last; eve; eve= eve->prev) if(eve->vn) eve->vn->f |= flag; + + return 'g'; +} + + +/* this is actually a recode of extrudeflag(), using proper edge/face select */ +/* hurms, doesnt use 'flag' yet, but its not called by primitive making stuff anyway */ static short extrudeflag_edge(short flag) { /* all select edges/faces: extrude */ @@ -467,7 +637,7 @@ static short extrudeflag_edge(short flag) EditMesh *em = G.editMesh; EditVert *eve, *nextve; EditEdge *eed, *nexted; - EditFace *efa, *nextfa, *efa2; + EditFace *efa, *nextfa; float nor[3]={0.0, 0.0, 0.0}; short del_old= 0; @@ -532,16 +702,8 @@ static short extrudeflag_edge(short flag) if(eed->v2->vn==NULL) eed->v2->vn= addvertlist(eed->v2->co); - if(eed->dir==1) efa2= addfacelist(eed->v1, eed->v2, eed->v2->vn, eed->v1->vn, NULL, NULL); - else efa2= addfacelist(eed->v2, eed->v1, eed->v1->vn, eed->v2->vn, NULL, NULL); - - if(eed->vn) { - /* btw, we dont do it in addfacelist, it copies edges too */ - efa= (EditFace *)eed->vn; - efa2->mat_nr= efa->mat_nr; - efa2->tf= efa->tf; - efa2->flag= efa->flag; - } + if(eed->dir==1) addfacelist(eed->v1, eed->v2, eed->v2->vn, eed->v1->vn, (EditFace *)eed->vn, NULL); + else addfacelist(eed->v2, eed->v1, eed->v1->vn, eed->v2->vn, (EditFace *)eed->vn, NULL); } } } @@ -620,11 +782,11 @@ static short extrudeflag_edge(short flag) } } + Normalise(nor); // translation normal grab + /* step 7: redo selection */ EM_clear_flag_all(SELECT); - Normalise(nor); // translation normal grab - for(eve= em->verts.first; eve; eve= eve->next) { if(eve->vn) { eve->vn->f |= SELECT; @@ -634,7 +796,8 @@ static short extrudeflag_edge(short flag) EM_select_flush(); - return 1; + if(nor[0]==0.0 && nor[1]==0.0 && nor[2]==0.0) return 'g'; + return 'n'; } short extrudeflag_vert(short flag) @@ -856,7 +1019,8 @@ short extrudeflag_vert(short flag) // since its vertex select mode now, it also deselects higher order EM_selectmode_flush(); - return 1; + if(nor[0]==0.0 && nor[1]==0.0 && nor[2]==0.0) return 'g'; + return 'n'; } /* generic extrude */ diff --git a/source/blender/src/editmesh_tools.c b/source/blender/src/editmesh_tools.c index 9f2b3f66c94..16a955e03c3 100644 --- a/source/blender/src/editmesh_tools.c +++ b/source/blender/src/editmesh_tools.c @@ -530,21 +530,31 @@ void hashvert_flag(int flag) void extrude_mesh(void) { - short a; + short nr, xmode= 0; TEST_EDITMESH - - if(okee("Extrude")==0) return; - a= extrudeflag(SELECT); + if(G.scene->selectmode & SCE_SELECT_VERTEX) + nr= pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3|Only Vertices%x4"); + else if(G.scene->selectmode & SCE_SELECT_EDGE) + nr= pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3"); + else + nr= pupmenu("Extrude %t|Region %x1||Individual Faces %x2"); + + if(nr<1) return; - if(a==0) { + if(nr==1) xmode= extrudeflag(SELECT); + else if(nr==4) xmode= extrudeflag_verts_indiv(SELECT); + else if(nr==3) xmode= extrudeflag_edges_indiv(SELECT); + else xmode= extrudeflag_face_indiv(SELECT); + + if(xmode==0) { error("No valid selection"); } else { EM_fgon_flags(); countall(); - transform('n'); + transform(xmode); } }