/** * $Id:$ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** * * The contents of this file may be used under the terms of either the GNU * General Public License Version 2 or later (the "GPL", see * http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or * later (the "BL", see http://www.blender.org/BL/ ) which has to be * bought from the Blender Foundation to become active, in which case the * above mentioned GPL option does not apply. * * The Original Code is Copyright (C) 2002 by NaN Holding BV. * All rights reserved. * * The Original Code is: all of this file. * * Contributor(s): none yet. * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ /* editface.c GRAPHICS * * maart 96 * * * Version: $Id: editface.c,v 1.9 2000/08/12 15:40:54 ton Exp $ */ #include "blender.h" #include "graphics.h" #include "render.h" TFace *lasttface=0; void set_lasttface() { Mesh *me; TFace *tface; int a; lasttface= 0; me= get_mesh(OBACT); if(me==0 || me->tface==0) return; tface= me->tface; a= me->totface; while(a--) { if(tface->flag & ACTIVE) { lasttface= tface; return; } tface++; } tface= me->tface; a= me->totface; while(a--) { if(tface->flag & SELECT) { lasttface= tface; return; } tface++; } tface= me->tface; a= me->totface; while(a--) { if((tface->flag & TF_HIDE)==0) { lasttface= tface; return; } tface++; } } void default_uv(float uv[][2], float size) { int dy; if(size>1.0) size= 1.0; dy= 1.0-size; uv[0][0]= 0; uv[0][1]= size+dy; uv[1][0]= 0; uv[1][1]= dy; uv[2][0]= size; uv[2][1]= dy; uv[3][0]= size; uv[3][1]= size+dy; } void default_tface(TFace *tface) { default_uv(tface->uv, 1.0); tface->col[0]= tface->col[1]= tface->col[2]= tface->col[3]= 0x80808080; tface->mode= TF_TEX; tface->flag= SELECT; tface->tpage= 0; tface->mode |= TF_DYNAMIC; } void make_tfaces(Mesh *me) { TFace *tface; int a; a= me->totface; if(a==0) return; tface= me->tface= callocN(a*sizeof(TFace), "tface"); while(a--) { default_tface(tface); tface++; } if(me->mcol) { mcol_to_tface(me, 1); } } void reveal_tface() { Mesh *me; TFace *tface; int a; me= get_mesh(OBACT); if(me==0 || me->tface==0 || me->totface==0) return; tface= me->tface; a= me->totface; while(a--) { if(tface->flag & TF_HIDE) { tface->flag |= SELECT; tface->flag -= TF_HIDE; } tface++; } allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWIMAGE, 0); } void hide_tface() { Mesh *me; TFace *tface; int a; me= get_mesh(OBACT); if(me==0 || me->tface==0 || me->totface==0) return; if(G.qual & LR_ALTKEY) { reveal_tface(); return; } tface= me->tface; a= me->totface; while(a--) { if(tface->flag & TF_HIDE); else { if(G.qual & LR_SHIFTKEY) { if( (tface->flag & SELECT)==0) tface->flag |= TF_HIDE; } else { if( (tface->flag & SELECT)) tface->flag |= TF_HIDE; } } if(tface->flag & TF_HIDE) tface->flag &= ~SELECT; tface++; } allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWIMAGE, 0); } void select_linked_tfaces() { Mesh *me; TFace *tface; MFace *mface; int a, doit=1; char *cpmain, *cp; me= get_mesh(OBACT); if(me==0 || me->tface==0 || me->totface==0) return; cp= cpmain= callocN(me->totvert, "cpmain"); while(doit) { doit= 0; /* select connected: array vullen */ tface= me->tface; mface= me->mface; a= me->totface; while(a--) { if(tface->flag & TF_HIDE); else if(tface->flag & SELECT) { if( mface->v3) { cpmain[mface->v1]= 1; cpmain[mface->v2]= 1; cpmain[mface->v3]= 1; if(mface->v4) cpmain[mface->v4]= 1; } } tface++; mface++; } /* omgekeerd: vanuit array vlakken selecteren */ tface= me->tface; mface= me->mface; a= me->totface; while(a--) { if(tface->flag & TF_HIDE); else if((tface->flag & SELECT)==0) { if( mface->v3) { if(mface->v4) { if(cpmain[mface->v4]) { tface->flag |= SELECT; doit= 1; } } if( cpmain[mface->v1] || cpmain[mface->v2] || cpmain[mface->v3] ) { tface->flag |= SELECT; doit= 1; } } } tface++; mface++; } } freeN(cpmain); allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWIMAGE, 0); } void deselectall_tface() { Mesh *me; TFace *tface; int a, sel; me= get_mesh(OBACT); if(me==0 || me->tface==0) return; tface= me->tface; a= me->totface; sel= 0; while(a--) { if(tface->flag & TF_HIDE); else if(tface->flag & SELECT) sel= 1; tface++; } tface= me->tface; a= me->totface; while(a--) { if(tface->flag & TF_HIDE); else { if(sel) tface->flag &= ~SELECT; else tface->flag |= SELECT; } tface++; } allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWIMAGE, 0); } void rotate_uv_tface() { Mesh *me; TFace *tface; MFace *mface; float u1, v1; int a; short mode; me= get_mesh(OBACT); if(me==0 || me->tface==0) return; mode= pupmenu("OK? %t|Rot UV %x1| Rot VertexCol %x2"); if(mode<1) return; tface= me->tface; mface= me->mface; a= me->totface; while(a--) { if(tface->flag & SELECT) { if(mode==1) { u1= tface->uv[0][0]; v1= tface->uv[0][1]; tface->uv[0][0]= tface->uv[1][0]; tface->uv[0][1]= tface->uv[1][1]; tface->uv[1][0]= tface->uv[2][0]; tface->uv[1][1]= tface->uv[2][1]; if(mface->v4) { tface->uv[2][0]= tface->uv[3][0]; tface->uv[2][1]= tface->uv[3][1]; tface->uv[3][0]= u1; tface->uv[3][1]= v1; } else { tface->uv[2][0]= u1; tface->uv[2][1]= v1; } } else if(mode==2) { u1= tface->col[0]; tface->col[0]= tface->col[1]; tface->col[1]= tface->col[2]; if(mface->v4) { tface->col[2]= tface->col[3]; tface->col[3]= u1; } else { tface->col[2]= u1; } } } tface++; mface++; } allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWIMAGE, 0); } void face_select() { Object *ob; Mesh *me; TFace *tface, *tsel; uint col; int a, index; short mval[2]; ob= OBACT; me= get_mesh(ob); if(me==0 || me->tface==0) return; if(ob->lay & G.vd->lay); else error("Active object not in this layer!"); if(curarea->win_swap==WIN_EQUAL) G.vd->flag |= V3D_NEEDBACKBUFDRAW; if(G.vd->flag & V3D_NEEDBACKBUFDRAW) { backdrawview3d(0); } getmouseco_areawin(mval); glReadPixels(mval[0]+curarea->winrct.xmin, mval[1]+curarea->winrct.ymin, ( mval[0]+curarea->winrct.xmin)-(mval[0]+curarea->winrct.xmin)+1, ( mval[1]+curarea->winrct.ymin)-( mval[1]+curarea->winrct.ymin)+1, GL_RGBA, GL_UNSIGNED_BYTE, &col); if(G.order==B_ENDIAN) SWITCH_INT(col); index= framebuffer_to_index(col); if(col==0 || index<=0 || index>me->totface) return; tsel= ( (TFace *)me->tface ) + (index-1); if(tsel->flag & TF_HIDE) return; /* clear flags */ tface= me->tface; a= me->totface; while(a--) { if(G.qual & LR_SHIFTKEY) tface->flag &= ~ACTIVE; else tface->flag &= ~(ACTIVE+SELECT); tface++; } tsel->flag |= ACTIVE; if(G.qual & LR_SHIFTKEY) { if(tsel->flag & SELECT) tsel->flag &= ~SELECT; else tsel->flag |= SELECT; } else tsel->flag |= SELECT; lasttface= tsel; /* image window redraw */ allqueue(REDRAWIMAGE, 0); allqueue(REDRAWBUTSGAME, 0); allqueue(REDRAWVIEW3D, 0); } void face_borderselect() { Mesh *me; TFace *tface; rcti rect; uint *rectm, *rt; int a, sx, sy, index, val; char *selar; me= get_mesh(OBACT); if(me==0 || me->tface==0) return; if(me->totface==0) return; val= get_border(&rect, 3); /* why readbuffer here? shouldn't be necessary */ glReadBuffer(GL_BACK); if(val) { selar= callocN(me->totface+1, "selar"); sx= (rect.xmax-rect.xmin+1); sy= (rect.ymax-rect.ymin+1); if(sx*sy<=0) return; rt=rectm= mallocN(sizeof(int)*sx*sy, "selrect"); glReadPixels(rect.xmin+curarea->winrct.xmin, rect.ymin+curarea->winrct.ymin, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE, rectm); if(G.order==B_ENDIAN) convert_rgba_to_abgr(sx*sy, rectm); a= sx*sy; while(a--) { if(*rt) { index= framebuffer_to_index(*rt); if(index<=me->totface) selar[index]= 1; } rt++; } tface= me->tface; for(a=1; a<=me->totface; a++, tface++) { if(selar[a]) { if(tface->flag & TF_HIDE); else { if(val==LEFTMOUSE) tface->flag |= SELECT; else tface->flag &= ~SELECT; } } } freeN(rectm); freeN(selar); allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWIMAGE, 0); } } void uv_autocalc_tface() { Mesh *me; TFace *tface; MFace *mface; MVert *mv; Object *ob; extern float cumapsize; /* buttons.c */ float dx, dy, ycor, min[3], cent[3], max[3], no[3], *loc, mat[4][4]; int a, b; short cox, coy, mode, adr[2]; me= get_mesh(ob=OBACT); if(me==0 || me->tface==0) return; if(me->totface==0) return; mode= pupmenu("UV Calculation %t|Cube %x2|Cylinder %x3|Sphere %x4|Bounds to 64 %x64|Bounds to 128 %x128|Standard 64 %x65|Standard 128 %x129|Standard 256 %x257| From Window %x5"); if(mode<1) return; if(mode==5 || mode==64 || mode==128) { /* standard 64/128: eerst window proj */ multmatrix(ob->obmat); Mat4SwapMat4(G.vd->persmat, mat); mygetsingmatrix(G.vd->persmat); tface= me->tface; mface= me->mface; for(a=0; atotface; a++, mface++, tface++) { if(tface->flag & SELECT) { if(mface->v3==0) continue; project_short( (me->mvert+mface->v1)->co, adr); if(adr[0]!=3200) { tface->uv[0][0]= ((float)adr[0])/curarea->winx; tface->uv[0][1]= ((float)adr[1])/curarea->winy; } project_short( (me->mvert+mface->v2)->co, adr); if(adr[0]!=3200) { tface->uv[1][0]= ((float)adr[0])/curarea->winx; tface->uv[1][1]= ((float)adr[1])/curarea->winy; } project_short( (me->mvert+mface->v3)->co, adr); if(adr[0]!=3200) { tface->uv[2][0]= ((float)adr[0])/curarea->winx; tface->uv[2][1]= ((float)adr[1])/curarea->winy; } if(mface->v4) { project_short( (me->mvert+mface->v4)->co, adr); if(adr[0]!=3200) { tface->uv[3][0]= ((float)adr[0])/curarea->winx; tface->uv[3][1]= ((float)adr[1])/curarea->winy; } } } } } if(mode==5); /* even afvangen ivm laatste else */ else if(mode==2) { tface= me->tface; mface= me->mface; mv= me->mvert; loc= ob->obmat[3]; fbutton(&cumapsize, 0.0001, 100.0, "Cubemap size"); for(a=0; atotface; a++, mface++, tface++) { if(tface->flag & SELECT) { if(mface->v3==0) continue; CalcNormFloat((mv+mface->v1)->co, (mv+mface->v2)->co, (mv+mface->v3)->co, no); no[0]= fabs(no[0]); no[1]= fabs(no[1]); no[2]= fabs(no[2]); cox=0; coy= 1; if(no[2]>=no[0] && no[2]>=no[1]); else if(no[1]>=no[0] && no[1]>=no[2]) coy= 2; else { cox= 1; coy= 2;} tface->uv[0][0]= 0.5+0.5*cumapsize*(loc[cox] + (mv+mface->v1)->co[cox]); tface->uv[0][1]= 0.5+0.5*cumapsize*(loc[coy] + (mv+mface->v1)->co[coy]); tface->uv[1][0]= 0.5+0.5*cumapsize*(loc[cox] + (mv+mface->v2)->co[cox]); tface->uv[1][1]= 0.5+0.5*cumapsize*(loc[coy] + (mv+mface->v2)->co[coy]); tface->uv[2][0]= 0.5+0.5*cumapsize*(loc[cox] + (mv+mface->v3)->co[cox]); tface->uv[2][1]= 0.5+0.5*cumapsize*(loc[coy] + (mv+mface->v3)->co[coy]); if(mface->v4) { tface->uv[3][0]= 0.5+0.5*cumapsize*(loc[cox] + (mv+mface->v4)->co[cox]); tface->uv[3][1]= 0.5+0.5*cumapsize*(loc[coy] + (mv+mface->v4)->co[coy]); } } } } else if ELEM(mode, 128, 64) { /* minmax */ min[0]= min[1]= 1.0; max[0]= max[1]= 0.0; tface= me->tface; mface= me->mface; for(a=0; atotface; a++, mface++, tface++) { if(tface->flag & SELECT) { if(mface->v3==0) continue; if(mface->v4) b= 3; else b= 2; for(; b>=0; b--) { min[0]= MIN2(tface->uv[b][0], min[0]); min[1]= MIN2(tface->uv[b][1], min[1]); max[0]= MAX2(tface->uv[b][0], max[0]); max[1]= MAX2(tface->uv[b][1], max[1]); } } } dx= max[0]-min[0]; dy= max[1]-min[1]; ycor= 1.0 - (mode/256.0); tface= me->tface; mface= me->mface; for(a=0; atotface; a++, mface++, tface++) { if(tface->flag & SELECT) { if(mface->v3==0) continue; if(mface->v4) b= 3; else b= 2; for(; b>=0; b--) { tface->uv[b][0]= ((tface->uv[b][0] - min[0])*(mode/256.0) )/dx; tface->uv[b][1]= ycor + ((tface->uv[b][1] - min[1])*(mode/256.0) )/dy; } } } } else if ELEM3(mode, 257, 129, 65) { mode--; tface= me->tface; for(a=0; atotface; a++, mface++, tface++) { if(tface->flag & SELECT) { default_uv(tface->uv, ((float)mode-1)/256.0); } } } else if(mode==3 || mode==4) { /* cyl or sphere */ /* calc centre */ INIT_MINMAX(min, max); tface= me->tface; mface= me->mface; for(a=0; atotface; a++, mface++, tface++) { if(tface->flag & SELECT) { if(mface->v3==0) continue; DO_MINMAX( (me->mvert+mface->v1)->co, min, max); DO_MINMAX( (me->mvert+mface->v2)->co, min, max); DO_MINMAX( (me->mvert+mface->v3)->co, min, max); if(mface->v4) DO_MINMAX( (me->mvert+mface->v3)->co, min, max); } } VecMidf(cent, min, max); tface= me->tface; mface= me->mface; for(a=0; atotface; a++, mface++, tface++) { if(tface->flag & SELECT) { if(mface->v3==0) continue; VecSubf(no, (me->mvert+mface->v1)->co, cent); if(mode==3) tubemap(no[0], no[1], no[2], tface->uv[0], &tface->uv[0][1]); else spheremap(no[0], no[1], no[2], tface->uv[0], &tface->uv[0][1]); VecSubf(no, (me->mvert+mface->v2)->co, cent); if(mode==3) tubemap(no[0], no[1], no[2], tface->uv[1], &tface->uv[1][1]); else spheremap(no[0], no[1], no[2], tface->uv[1], &tface->uv[1][1]); VecSubf(no, (me->mvert+mface->v3)->co, cent); if(mode==3) tubemap(no[0], no[1], no[2], tface->uv[2], &tface->uv[2][1]); else spheremap(no[0], no[1], no[2], tface->uv[2], &tface->uv[2][1]); if(mface->v4) { VecSubf(no, (me->mvert+mface->v4)->co, cent); if(mode==3) tubemap(no[0], no[1], no[2], tface->uv[3], &tface->uv[3][1]); else spheremap(no[0], no[1], no[2], tface->uv[3], &tface->uv[3][1]); } } } } /* clipping and wrapping */ if(G.sima && G.sima->flag & SI_CLIP_UV) { tface= me->tface; mface= me->mface; for(a=0; atotface; a++, mface++, tface++) { if(tface->flag & SELECT) { if(mface->v3==0) continue; dx= dy= 0; if(mface->v4) b= 3; else b= 2; for(; b>=0; b--) { while(tface->uv[b][0] + dx < 0.0) dx+= 0.5; while(tface->uv[b][0] + dx > 1.0) dx-= 0.5; while(tface->uv[b][1] + dy < 0.0) dy+= 0.5; while(tface->uv[b][1] + dy > 1.0) dy-= 0.5; } if(mface->v4) b= 3; else b= 2; for(; b>=0; b--) { tface->uv[b][0]+= dx; CLAMP(tface->uv[b][0], 0.0, 1.0); tface->uv[b][1]+= dy; CLAMP(tface->uv[b][1], 0.0, 1.0); } } } } allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWIMAGE, 0); loadmatrix(G.vd->viewmat); Mat4SwapMat4(G.vd->persmat, mat); } void set_faceselect() /* toggle */ { Object *ob; Mesh *me; addqueue(curarea->headwin, REDRAW, 1); if(G.f & G_FACESELECT) G.f &= ~G_FACESELECT; else G.f |= G_FACESELECT; allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWBUTSGAME, 0); allqueue(REDRAWBUTSEDIT, 0); allqueue(REDRAWIMAGE, 0); ob= OBACT; me= get_mesh(ob); if(me && me->tface==NULL) make_tfaces(me); if(G.f & G_FACESELECT) { setcursor_space(SPACE_VIEW3D, CURSOR_FACESEL); if(me) set_lasttface(); } else if((G.f & G_VERTEXPAINT)==0) { if(me) reveal_tface(); setcursor_space(SPACE_VIEW3D, CURSOR_STD); } countall(); }