forked from bartvdbraak/blender
Four new extrude possibilities;
- Individual faces Keeps Mesh manifold, so removes old faces always. Also uses a transform based on different vectors per vertex. - Only edges Just extrudes the edges (not really 'individual', the edges still share the vertices. Uses same transform as normal extrude for that reason - Only Vertices Uses normal transform after extrude Also changed code a bit, to detect whether to call a normal-based transform after extrude, or whether to call normal grabber. For example when you just extrude 1 edge, it uses normal grabber. Note; extruding an entire sphere goes OK with 'individual faces'. for other extrudes you should press 's key' when in transform. Just cannot predict (yet) when one method has preference over another.
This commit is contained in:
parent
295f11ea70
commit
4c827e73e2
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user