diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2004-04-01 16:55:12 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2004-04-01 16:55:12 +0400 |
commit | d7f3f6672815f2aaebfdefae41082ee861193cfe (patch) | |
tree | d96d739652531ecdf0088e083bf6ad179aef7131 /source/blender/src/editsima.c | |
parent | d204f77251fb7559ea8ee1186a4796c26706c56b (diff) |
New UV editor / Image Window features:
- Draw Faces in the UV editor
- Draw Faces, selected in the UV editor, in the 3D view
- Draw Shadow Mesh in the UV editor (for faces unselected in the 3D view)
- Select Linked UVs (LKEY)
- Unlink Selection (Alt+LKEY)
- Stick (Local) UVs to Mesh Vertex on selection
- Active Face Select
- Reload Image
- Show / Hide Faces in the UV editor (H, Shift+H, Alt+H)
- Proportional Editing (O, Shift+O)
- Stitch, Limit Stitch UVs (snap by mesh vertex)
- Weld / Align UVs (WKEY)
- UVs Snap to Pixels on/off switch
- RMB in Texture Paint or Vertex Paint mode picks color
- Select Inverse in Faceselect mode
I hope these are all the features that were commited. The new UV Mapping
panel (and code) will follow later.
Diffstat (limited to 'source/blender/src/editsima.c')
-rw-r--r-- | source/blender/src/editsima.c | 877 |
1 files changed, 784 insertions, 93 deletions
diff --git a/source/blender/src/editsima.c b/source/blender/src/editsima.c index 2eb40ba0d2e..173655907e6 100644 --- a/source/blender/src/editsima.c +++ b/source/blender/src/editsima.c @@ -31,6 +31,7 @@ */ #include <stdlib.h> +#include <string.h> #include <math.h> #ifdef HAVE_CONFIG_H @@ -82,6 +83,21 @@ #include "blendef.h" #include "mydevice.h" +struct uvvertsort { + unsigned int v; + unsigned char tf_sel; + char flag; + TFace *tface; +}; + +static int compuvvert(const void *u1, const void *u2) +{ + const struct uvvertsort *v1=u1, *v2=u2; + if (v1->v > v2->v) return 1; + else if (v1->v < v2->v) return -1; + return 0; +} + static int is_uv_tface_editing_allowed(void) { Mesh *me; @@ -95,6 +111,18 @@ static int is_uv_tface_editing_allowed(void) return 1; } +static void setLinkedLimit(float *limit) +{ + if(G.sima->image && G.sima->image->ibuf && G.sima->image->ibuf->x > 0 && + G.sima->image->ibuf->y > 0) { + limit[0]= 5.0/(float)G.sima->image->ibuf->x; + limit[1]= 5.0/(float)G.sima->image->ibuf->y; + } + else + limit[0]= limit[1]= 5.0/256.0; +} + + void clever_numbuts_sima(void) { float ocent[2], cent[2]= {0.0, 0.0}; @@ -190,25 +218,31 @@ static void sima_pixelgrid(float *loc, float sx, float sy) float y; float x; - if(G.sima->image && G.sima->image->ibuf) { - x= G.sima->image->ibuf->x; - y= G.sima->image->ibuf->y; - - sx= floor(x*sx)/x; - if(G.sima->flag & SI_CLIP_UV) { - CLAMP(sx, 0, 1.0); - } + if(G.sima->flag & SI_NOPIXELSNAP) { loc[0]= sx; - - sy= floor(y*sy)/y; - if(G.sima->flag & SI_CLIP_UV) { - CLAMP(sy, 0, 1.0); - } loc[1]= sy; } else { - loc[0]= sx; - loc[1]= sy; + if(G.sima->image && G.sima->image->ibuf) { + x= G.sima->image->ibuf->x; + y= G.sima->image->ibuf->y; + + sx= floor(x*sx)/x; + if(G.sima->flag & SI_CLIP_UV) { + CLAMP(sx, 0, 1.0); + } + loc[0]= sx; + + sy= floor(y*sy)/y; + if(G.sima->flag & SI_CLIP_UV) { + CLAMP(sy, 0, 1.0); + } + loc[1]= sy; + } + else { + loc[0]= sx; + loc[1]= sy; + } } } @@ -299,18 +333,25 @@ void transform_tface_uv(int mode) TFace *tface; Mesh *me; TransVert *transmain, *tv; + + float dist, xdist, ydist, aspx, aspy; float asp, dx1, dx2, dy1, dy2, phi, dphi, co, si; float xref=1.0, yref=1.0, size[2], sizefac; float dx, dy, dvec2[2], dvec[2], div, cent[2]; float x, y, min[2], max[2], vec[2], xtra[2], ivec[2]; - int xim, yim, tot=0, a, b, firsttime=1, afbreek=0, midtog= 0, proj = 0; + int xim, yim, tot=0, a, b, firsttime=1, afbreek=0, align= 0; + int propmode= 0, proptot= 0, midtog= 0, proj= 0, prop_recalc= 1; unsigned short event = 0; short mval[2], val, xo, yo, xn, yn, xc, yc; - char str[32]; + char str[80]; + extern float prop_size, prop_cent[3]; + extern int prop_mode; if( is_uv_tface_editing_allowed()==0 ) return; me= get_mesh(OBACT); + if(G.f & G_PROPORTIONAL) propmode= 1; + min[0]= min[1]= 10000.0; max[0]= max[1]= -10000.0; @@ -323,37 +364,57 @@ void transform_tface_uv(int mode) else { xim= yim= 256; } - /* which vertices are involved */ - - for(a=me->totface, tface= me->tface, mface= me->mface; a>0; a--, tface++, mface++) { - if((tface->flag & TF_SELECT) && mface->v3) { + aspx = (float)xim/256.0; + aspy = (float)yim/256.0; + + /* which vertices are involved? */ + tface= me->tface; + mface= me->mface; + for(a=me->totface; a>0; a--, tface++, mface++) { + if(tface->flag & TF_SELECT) { if(tface->flag & TF_SEL1) tot++; if(tface->flag & TF_SEL2) tot++; if(tface->flag & TF_SEL3) tot++; - if(tface->flag & TF_SEL4) tot++; + if(mface->v4 && (tface->flag & TF_SEL4)) tot++; + if(propmode) { + if(mface->v4) proptot+=4; + else proptot+=3; + } } } if(tot==0) return; + if(propmode) tot= proptot; + + G.moving= 1; + prop_size/= 3; tv=transmain= MEM_callocN(tot*sizeof(TransVert), "transmain"); - for(a=me->totface, tface= me->tface, mface= me->mface; a>0; a--, tface++, mface++) { - if((tface->flag & TF_SELECT) && mface->v3) { - if(tface->flag & TF_SEL1) { + tface= me->tface; + mface= me->mface; + for(a=me->totface; a>0; a--, tface++, mface++) { + if(mface->v3 && tface->flag & TF_SELECT) { + if (tface->flag & TF_SEL1 || propmode) { tv->loc= tface->uv[0]; + if(tface->flag & TF_SEL1) tv->flag= 1; tv++; } - if(tface->flag & TF_SEL2) { + if (tface->flag & TF_SEL2 || propmode) { tv->loc= tface->uv[1]; + if(tface->flag & TF_SEL2) tv->flag= 1; tv++; } - if(tface->flag & TF_SEL3) { + if (tface->flag & TF_SEL3 || propmode) { tv->loc= tface->uv[2]; + if(tface->flag & TF_SEL3) tv->flag= 1; tv++; } - if(tface->flag & TF_SEL4) { - tv->loc= tface->uv[3]; - tv++; + if(mface->v4) { + if (tface->flag & TF_SEL4 || propmode) { + tv->loc= tface->uv[3]; + if(tface->flag & TF_SEL4) tv->flag= 1; + tv++; + } } } } @@ -363,12 +424,16 @@ void transform_tface_uv(int mode) while(a--) { tv->oldloc[0]= tv->loc[0]; tv->oldloc[1]= tv->loc[1]; - DO_MINMAX2(tv->loc, min, max); + if(tv->flag) { + DO_MINMAX2(tv->loc, min, max); + } tv++; } - + cent[0]= (min[0]+max[0])/2.0; cent[1]= (min[1]+max[1])/2.0; + prop_cent[0]= cent[0]; + prop_cent[1]= cent[1]; ipoco_to_areaco_noclip(G.v2d, cent, mval); xc= mval[0]; @@ -388,8 +453,35 @@ void transform_tface_uv(int mode) while(afbreek==0) { getmouseco_areawin(mval); - if(mval[0]!=xo || mval[1]!=yo || firsttime) { - + if(((mval[0]!=xo || mval[1]!=yo) && !(mode=='w')) || firsttime) { + if(propmode && prop_recalc && transmain) { + a= tot; + tv= transmain; + + while(a--) { + if(tv->oldloc[0]<min[0]) xdist= tv->oldloc[0]-min[0]; + else if(tv->oldloc[0]>max[0]) xdist= tv->oldloc[0]-max[0]; + else xdist= 0.0; + xdist*= aspx; + + if(tv->oldloc[1]<min[1]) ydist= tv->oldloc[1]-min[1]; + else if(tv->oldloc[1]>max[1]) ydist= tv->oldloc[1]-max[1]; + else ydist= 0.0; + ydist*= aspy; + + dist= sqrt(xdist*xdist + ydist*ydist); + if(dist==0.0) tv->fac= 1.0; + else if(dist > prop_size) tv->fac= 0.0; + else { + dist= (prop_size-dist)/prop_size; + if(prop_mode==1) + tv->fac= 3.0*dist*dist - 2.0*dist*dist*dist; + else tv->fac= dist*dist; + } + tv++; + } + prop_recalc= 0; + } if(mode=='g') { dx= mval[0]- xo; @@ -418,13 +510,22 @@ void transform_tface_uv(int mode) if(vec[1]> 1.0-max[1]) vec[1]= 1.0-max[1]; } tv= transmain; - for(a=0; a<tot; a++, tv++) { - - x= tv->oldloc[0]+vec[0]; - y= tv->oldloc[1]+vec[1]; + if (propmode) { + for(a=0; a<tot; a++, tv++) { + x= tv->oldloc[0]+tv->fac*vec[0]; + y= tv->oldloc[1]+tv->fac*vec[1]; - sima_pixelgrid(tv->loc, x, y); + sima_pixelgrid(tv->loc, x, y); + } + } else { + for(a=0; a<tot; a++, tv++) { + x= tv->oldloc[0]+vec[0]; + y= tv->oldloc[1]+vec[1]; + + sima_pixelgrid(tv->loc, x, y); + } } + ivec[0]= (vec[0]*xim); ivec[1]= (vec[1]*yim); @@ -447,7 +548,7 @@ void transform_tface_uv(int mode) if(G.qual & LR_SHIFTKEY) phi+= dphi/30.0; else phi+= dphi; - + apply_keyb_grid(&phi, 0.0, (5.0/180)*M_PI, (1.0/180)*M_PI, U.flag & USER_AUTOROTGRID); dx1= dx2; @@ -457,10 +558,12 @@ void transform_tface_uv(int mode) si= sin(phi); asp= (float)yim/(float)xim; - tv= transmain; for(a=0; a<tot; a++, tv++) { - + if(propmode) { + co= cos(phi*tv->fac); + si= sin(phi*tv->fac); + } x= ( co*( tv->oldloc[0]-cent[0]) - si*asp*(tv->oldloc[1]-cent[1]) ) +cent[0]; y= ( si*( tv->oldloc[0]-cent[0])/asp + co*(tv->oldloc[1]-cent[1]) ) +cent[1]; sima_pixelgrid(tv->loc, x, y); @@ -473,15 +576,12 @@ void transform_tface_uv(int mode) } } - sprintf(str, "Rot: %.3f ", phi*180.0/M_PI); headerprint(str); } } else if(mode=='s') { - - size[0]=size[1]= (sqrt( (float)((yc-mval[1])*(yc-mval[1])+(mval[0]-xc)*(mval[0]-xc)) ))/sizefac; - + size[0]= size[1]= (sqrt((float)((yc-mval[1])*(yc-mval[1])+(mval[0]-xc)*(mval[0]-xc))))/sizefac; if(midtog) size[proj]= 1.0; apply_keyb_grid(size, 0.0, 0.1, 0.01, U.flag & USER_AUTOSIZEGRID); @@ -529,22 +629,62 @@ void transform_tface_uv(int mode) /* } */ tv= transmain; - for(a=0; a<tot; a++, tv++) { + if (propmode) { + for(a=0; a<tot; a++, tv++) { + + x= (tv->fac*size[0] + 1.00-tv->fac)*(tv->oldloc[0]-cent[0])+ cent[0] + xtra[0]; + y= (tv->fac*size[1] + 1.00-tv->fac)*(tv->oldloc[1]-cent[1])+ cent[1] + xtra[1]; + sima_pixelgrid(tv->loc, x, y); + } + + } else { + for(a=0; a<tot; a++, tv++) { - x= size[0]*(tv->oldloc[0]-cent[0])+ cent[0] + xtra[0]; - y= size[1]*(tv->oldloc[1]-cent[1])+ cent[1] + xtra[1]; - sima_pixelgrid(tv->loc, x, y); + x= size[0]*(tv->oldloc[0]-cent[0])+ cent[0] + xtra[0]; + y= size[1]*(tv->oldloc[1]-cent[1])+ cent[1] + xtra[1]; + sima_pixelgrid(tv->loc, x, y); + } } - sprintf(str, "sizeX: %.3f sizeY: %.3f ", size[0], size[1]); + sprintf(str, "sizeX: %.3f sizeY: %.3f", size[0], size[1]); headerprint(str); + } + else if(mode=='w') { /* weld / align */ + tv= transmain; + for(a=0; a<tot; a++, tv++) { + x= tv->oldloc[0]; + y= tv->oldloc[1]; + if(align==0) { + x= cent[0]; + y= cent[1]; + } + else if(align==1) y= cent[1]; + else if(align==2) x= cent[0]; + + tv->loc[0]= x; + tv->loc[1]= y; + + if(G.sima->flag & SI_CLIP_UV) { + if(tv->loc[0]<0.0) tv->loc[0]= 0.0; + else if(tv->loc[0]>1.0) tv->loc[0]= 1.0; + if(tv->loc[1]<0.0) tv->loc[1]= 0.0; + else if(tv->loc[1]>1.0) tv->loc[1]= 1.0; + } + } + if(align==0) + sprintf(str, "Weld (X: Align along X, Y: Align along Y)"); + else if(align==1) + sprintf(str, "X Axis Align (W: Weld, Y: Align along Y)"); + else if(align==2) + sprintf(str, "Y Axis Align (W: Weld, X: Align along X)"); + headerprint(str); } xo= mval[0]; yo= mval[1]; - if(G.sima->lock) force_draw_plus(SPACE_VIEW3D); + if(G.sima->lock || mode=='w') force_draw_plus(SPACE_VIEW3D); else force_draw(); firsttime= 0; @@ -564,27 +704,69 @@ void transform_tface_uv(int mode) afbreek= 1; break; case MIDDLEMOUSE: - midtog= ~midtog; if(midtog) { if( abs(mval[0]-xn) > abs(mval[1]-yn)) proj= 1; else proj= 0; firsttime= 1; } - break; + case WHEELDOWNMOUSE: + case PADPLUSKEY: + if(propmode) { + prop_size*= 1.1; + prop_recalc= 1; + firsttime= 1; + } + break; + case WHEELUPMOUSE: + case PADMINUS: + if(propmode) { + prop_size*= 0.90909090; + prop_recalc= 1; + firsttime= 1; + } + break; + case WKEY: case XKEY: case YKEY: - if(event==XKEY) xref= -xref; - else yref= -yref; - + if(mode!='w') { + if(event==XKEY) xref= -xref; + else yref= -yref; + } + else { + if(event==WKEY) align= 0; + else if(event==XKEY) align= 1; + else align= 2; + } firsttime= 1; break; default: arrows_move_cursor(event); } } - if(afbreek) break; + if(afbreek) { + if(!(event==ESCKEY || event == RIGHTMOUSE) && + mode=='w' && align>0) { + /* implicit commit */ + tv= transmain; + for(a=0; a<tot; a++, tv++) { + tv->oldloc[0]= tv->loc[0]; + tv->oldloc[1]= tv->loc[1]; + firsttime=1; + } + midtog= 1; + if(align==1) proj= 0; + else proj= 1; + mode= 'g'; + getmouseco_areawin(mval); + xo= mval[0]; + yo= mval[1]; + afbreek= 0; + } + else + break; + } } } @@ -598,7 +780,10 @@ void transform_tface_uv(int mode) MEM_freeN(transmain); if(mode=='g') if(G.sima->flag & SI_BE_SQUARE) be_square_tface_uv(me); - + + G.moving= 0; + prop_size*= 3; + makeDispList(OBACT); allqueue(REDRAWVIEW3D, 0); scrarea_queue_headredraw(curarea); @@ -641,90 +826,262 @@ void select_swap_tface_uv(void) allqueue(REDRAWIMAGE, 0); } +static int msel_hit(float *limit, unsigned int *hitarray, unsigned int vertexid, float **uv, float *uv2) +{ + int i; + for(i=0; i< 4; i++) { + if(hitarray[i] == vertexid) { + if(G.sima->flag & SI_LOCALSTICKY) { + if(fabs(uv[i][0]-uv2[0]) < limit[0] && + fabs(uv[i][1]-uv2[1]) < limit[1]) + return 1; + } + else return 1; + } + } + return 0; +} + void mouse_select_sima(void) { Mesh *me; - TFace *tface; - MFace *mface; - int temp, dist=100; - int a; - short mval[2], uval[2], val = 0; - char *flagpoin =0; + TFace *tface, *closesttface= NULL; + MFace *mface, *closestmface= NULL; + int a, redraw= 0, uvcent[2], selectsticky= 0, sticky, actface; + int temp, dist= 0x7FFFFFF, fdist= 0x7FFFFFF, fdistmin= 0x7FFFFFF; + short mval[2], uval[2], val= 0; + char *flagpoin= 0; + unsigned int hitvert[4]= {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF}; + float *hituv[4], limit[2]; if( is_uv_tface_editing_allowed()==0 ) return; me= get_mesh(OBACT); - getmouseco_areawin(mval); + setLinkedLimit(limit); + actface= (G.qual & LR_ALTKEY || G.sima->flag & SI_SELACTFACE); + sticky= (G.qual & LR_CTRLKEY || G.sima->flag & SI_STICKYUVS || + G.sima->flag & SI_LOCALSTICKY); + + /* go for one run through all faces. collect all information needed */ mface= me->mface; - for(a=me->totface, tface= me->tface; a>0; a--, tface++, mface++) { - - if(tface->flag & TF_SELECT) { + tface= me->tface; + for(a=me->totface; a>0; a--, tface++, mface++) { + if(tface->flag & TF_SELECT && mface->v3) { uvco_to_areaco_noclip(tface->uv[0], uval); - temp= abs(mval[0]- uval[0])+ abs(mval[1]- uval[1]); - if( tface->flag & TF_SEL1) temp+=5; + uvcent[0]= uval[0]; + uvcent[1]= uval[1]; + temp= abs(mval[0]-uval[0]) + abs(mval[1]-uval[1]); + if(tface->flag & TF_SEL1) temp += 5; if(temp<dist) { flagpoin= &tface->flag; dist= temp; val= TF_SEL1; + hitvert[1]= hitvert[2]= hitvert[3]= 0xFFFFFFFF; + hitvert[0]= mface->v1; + hituv[0]= tface->uv[0]; } uvco_to_areaco_noclip(tface->uv[1], uval); - temp= abs(mval[0]- uval[0])+ abs(mval[1]- uval[1]); - if( tface->flag & TF_SEL2) temp+=5; + temp= abs(mval[0]-uval[0]) + abs(mval[1]-uval[1]); + uvcent[0] += uval[0]; + uvcent[1] += uval[1]; + if(tface->flag & TF_SEL2) temp += 5; if(temp<dist) { flagpoin= &tface->flag; dist= temp; val= TF_SEL2; + hitvert[0]= hitvert[2]= hitvert[3]= 0xFFFFFFFF; + hitvert[1]= mface->v2; + hituv[1]= tface->uv[1]; } uvco_to_areaco_noclip(tface->uv[2], uval); - temp= abs(mval[0]- uval[0])+ abs(mval[1]- uval[1]); - if( tface->flag & TF_SEL3) temp+=5; + temp= abs(mval[0]-uval[0]) + abs(mval[1]-uval[1]); + uvcent[0] += uval[0]; + uvcent[1] += uval[1]; + if(tface->flag & TF_SEL3) temp += 5; if(temp<dist) { flagpoin= &tface->flag; dist= temp; val= TF_SEL3; + hitvert[0]= hitvert[1]= hitvert[3]= 0xFFFFFFFF; + hitvert[2]= mface->v3; + hituv[2]= tface->uv[2]; } if(mface->v4) { uvco_to_areaco_noclip(tface->uv[3], uval); - temp= abs(mval[0]- uval[0])+ abs(mval[1]- uval[1]); - if( tface->flag & TF_SEL4) temp+=5; + uvcent[0] += uval[0]; + uvcent[1] += uval[1]; + temp= abs(mval[0]-uval[0]) + abs(mval[1]-uval[1]); + if(tface->flag & TF_SEL4) temp += 5; if(temp<dist) { flagpoin= &tface->flag; dist= temp; val= TF_SEL4; + hitvert[0]= hitvert[1]= hitvert[2]= 0xFFFFFFFF; + hitvert[3] = mface->v4; + hituv[3]= tface->uv[3]; } + uvcent[0] /= 4; + uvcent[1] /= 4; + } + else { + uvcent[0] /= 3; + uvcent[1] /= 3; } + /* find face closest to mouse */ + if(actface) { + fdist= abs(mval[0]- uvcent[0])+ abs(mval[1]- uvcent[1]); + if (fdist < fdistmin){ + closesttface= tface; + closestmface= mface; + fdistmin= fdist; + } + } } } - if(flagpoin) { - if(G.qual & LR_SHIFTKEY) { - if(*flagpoin & val) *flagpoin &= ~val; - else *flagpoin |= val; + if(!flagpoin) + return; + + if(actface && closesttface) { + closesttface->flag |= TF_ACTIVE; + hitvert[0]= closestmface->v1; + hituv[0]= closesttface->uv[0]; + hitvert[1]= closestmface->v2; + hituv[1]= closesttface->uv[1]; + hitvert[2]= closestmface->v3; + hituv[2]= closesttface->uv[2]; + if(closestmface->v4) { + hitvert[3]= closestmface->v4; + hituv[3]= closesttface->uv[3]; } + } + + if(G.qual & LR_SHIFTKEY) { + /* (de)select face */ + if(actface) { + if(!(~closesttface->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) + && (!closestmface->v4 || closesttface->flag & TF_SEL4)) { + closesttface->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); + selectsticky= 0; + } + else { + closesttface->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4; + selectsticky= 1; + } + } + /* (de)select uv node */ else { - for(a=me->totface, tface= me->tface; a>0; a--, tface++) { - if(tface->flag & TF_SELECT) { - tface->flag &= ~(TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4); + if(*flagpoin & val) { + *flagpoin &= ~val; + selectsticky= 0; + } + else { + *flagpoin |= val; + selectsticky= 1; + } + } + + /* (de)select sticky uv nodes */ + if(sticky || actface) { + mface= me->mface; + tface= me->tface; + /* deselect */ + if(selectsticky==0) { + for(a=me->totface; a>0; a--, tface++, mface++) { + if(!(tface->flag & TF_SELECT && mface->v3)) continue; + if(closesttface && tface!=closesttface) + tface->flag &=~ TF_ACTIVE; + if (!sticky) continue; + + if(msel_hit(limit,hitvert,mface->v1,hituv,tface->uv[0])) + tface->flag &= ~TF_SEL1; + if(msel_hit(limit,hitvert,mface->v2,hituv,tface->uv[1])) + tface->flag &= ~TF_SEL2; + if(msel_hit(limit,hitvert,mface->v3,hituv,tface->uv[2])) + tface->flag &= ~TF_SEL3; + if (mface->v4) + if(msel_hit(limit,hitvert,mface->v4,hituv,tface->uv[3])) + tface->flag &= ~TF_SEL4; } } - - *flagpoin |= val; + /* select */ + else { + for(a=me->totface; a>0; a--, tface++, mface++) { + if(!(tface->flag & TF_SELECT && mface->v3)) continue; + if(closesttface && tface!=closesttface) + tface->flag &=~ TF_ACTIVE; + if (!sticky) continue; + + if(msel_hit(limit,hitvert,mface->v1,hituv,tface->uv[0])) + tface->flag |= TF_SEL1; + if(msel_hit(limit,hitvert,mface->v2,hituv,tface->uv[1])) + tface->flag |= TF_SEL2; + if(msel_hit(limit,hitvert,mface->v3,hituv,tface->uv[2])) + tface->flag |= TF_SEL3; + if (mface->v4) + if(msel_hit(limit,hitvert,mface->v4,hituv,tface->uv[3])) + tface->flag |= TF_SEL4; + } + } + } + } + else { + /* select face and deselect other faces */ + if(actface) { + mface= me->mface; + tface= me->tface; + for(a=me->totface; a>0; a--, tface++, mface++) { + tface->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); + if(closesttface && tface!=closesttface) + tface->flag &=~ TF_ACTIVE; + } + if(closesttface) + closesttface->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); + redraw= 1; + } + + /* deselect uvs, and select sticky uvs */ + mface= me->mface; + tface= me->tface; + for(a=me->totface; a>0; a--, tface++, mface++) { + if(tface->flag & TF_SELECT && mface->v3) { + if(!actface) tface->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); + if(!sticky) continue; + + if(msel_hit(limit,hitvert,mface->v1,hituv,tface->uv[0])) + tface->flag |=TF_SEL1; + if(msel_hit(limit,hitvert,mface->v2,hituv,tface->uv[1])) + tface->flag |=TF_SEL2; + if(msel_hit(limit,hitvert,mface->v3,hituv,tface->uv[2])) + tface->flag |=TF_SEL3; + if(mface->v4) + if(msel_hit(limit,hitvert,mface->v4,hituv,tface->uv[3])) + tface->flag |=TF_SEL4; + } } + if(!actface) + *flagpoin |= val; + } + if(redraw || G.f & G_DRAWFACES) { + force_draw_plus(SPACE_VIEW3D); + } + else { glDrawBuffer(GL_FRONT); draw_tfaces(); - glFlush(); // at OSX, a flush pops up the "frontbuffer" (it does a swap, doh!) + /*at OSX, a flush pops up the "frontbuffer" (it does a swap, doh!)*/ + glFlush(); glDrawBuffer(GL_BACK); - - std_rmouse_transform(transform_tface_uv); } + + std_rmouse_transform(transform_tface_uv); } void borderselect_sima(void) @@ -859,10 +1216,16 @@ void uvedit_selectionCB(short selecting, Object *editobj, short *mval, float rad tface++; mface++; } - // force_draw() is no good here... - glDrawBuffer(GL_FRONT); - draw_tfaces(); - glDrawBuffer(GL_BACK); + + if(G.f & G_DRAWFACES) { /* full redraw only if necessary */ + draw_sel_circle(0, 0, 0, 0, 0); /* signal */ + force_draw_plus(SPACE_VIEW3D); + } + else { /* force_draw() is no good here... */ + glDrawBuffer(GL_FRONT); + draw_tfaces(); + glDrawBuffer(GL_BACK); + } } } @@ -909,3 +1272,331 @@ void mouseco_to_curtile(void) scrarea_queue_winredraw(curarea); } } + +void hide_tface_uv(int swap) +{ + Mesh *me; + TFace *tface; + MFace *mface; + int a; + + if( is_uv_tface_editing_allowed()==0 ) return; + me= get_mesh(OBACT); + + if(swap) { + mface= me->mface; + for(a=me->totface, tface= me->tface; a>0; a--, tface++, mface++) { + if(mface->v3 && tface->flag & TF_SELECT) { + if((tface->flag & (TF_SEL1|TF_SEL2|TF_SEL3))==0) { + if(!mface->v4) + tface->flag &= ~TF_SELECT; + else if(!(tface->flag & TF_SEL4)) + tface->flag &= ~TF_SELECT; + } + } + } + } else { + mface= me->mface; + for(a=me->totface, tface= me->tface; a>0; a--, tface++, mface++) { + if(mface->v3 && tface->flag & TF_SELECT) { + if(tface->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) + tface->flag &= ~TF_SELECT; + else if(mface->v4 && tface->flag & TF_SEL4) + tface->flag &= ~TF_SELECT; + } + } + } + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWIMAGE, 0); +} + +void reveal_tface_uv(void) +{ + Mesh *me; + TFace *tface; + MFace *mface; + int a; + + if( is_uv_tface_editing_allowed()==0 ) return; + me= get_mesh(OBACT); + + mface= me->mface; + for(a=me->totface, tface= me->tface; a>0; a--, tface++, mface++) + if(mface->v3 && !(tface->flag & TF_HIDE)) + if(!(tface->flag & TF_SELECT)) + tface->flag |= (TF_SELECT|TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); + + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWIMAGE, 0); +} + +void stitch_uv_tface(int mode) +{ + MFace *mface; + TFace *tface; + Mesh *me; + unsigned int a, b, c, vtot, vtot2, tot; + float newuv[2], limit[2], *uv, *uv1; + struct uvvertsort *sortblock, *sb, *sb1, *sb2; + + if( is_uv_tface_editing_allowed()==0 ) return; + + limit[0]= limit[1]= 20.0; + if(mode==1) { + add_numbut(0, NUM|FLO, "Limit:", 0.1, 1000.0, &limit[0], NULL); + if (!do_clever_numbuts("Stitch UVs", 1, REDRAW)) + return; + } + + if(G.sima->image && G.sima->image->ibuf && G.sima->image->ibuf->x > 0 && + G.sima->image->ibuf->y > 0) { + limit[1]= limit[0]/(float)G.sima->image->ibuf->y; + limit[0]= limit[0]/(float)G.sima->image->ibuf->x; + } + else + limit[0]= limit[1]= limit[0]/256.0; + + me= get_mesh(OBACT); + + tot= 0; + mface= me->mface; + for(a=me->totface, tface=me->tface; a>0; a--, tface++, mface++) { + if((tface->flag & TF_SELECT) && mface->v3) { + if(tface->flag & TF_SEL1) tot++; + if(tface->flag & TF_SEL2) tot++; + if(tface->flag & TF_SEL3) tot++; + if(mface->v4 && tface->flag & TF_SEL4) tot++; + } + } + if(tot==0) return; + + sb= sortblock= MEM_callocN(sizeof(struct uvvertsort)*tot,"sortstitchuv"); + + mface= me->mface; + for(a=me->totface, tface=me->tface; a>0; a--, tface++, mface++) { + if((tface->flag & TF_SELECT) && mface->v3) { + if(tface->flag & TF_SEL1) { + sb->v= mface->v1; + sb->tface= tface; + sb->tf_sel= 0; + sb++; + } + if(tface->flag & TF_SEL2) { + sb->v= mface->v2; + sb->tface= tface; + sb->tf_sel= 1; + sb++; + } + if(tface->flag & TF_SEL3) { + sb->v= mface->v3; + sb->tface= tface; + sb->tf_sel= 2; + sb++; + } + if(mface->v4 && tface->flag & TF_SEL4) { + sb->v= mface->v4; + sb->tface = tface; + sb->tf_sel= 3; + sb++; + } + } + } + + /* sort by vertex */ + qsort(sortblock, tot, sizeof(struct uvvertsort), compuvvert); + + if(mode==0) { + for (a=0, sb=sortblock; a<tot; a+=vtot, sb+=vtot) { + newuv[0]= 0; newuv[1]= 0; + vtot= 0; + + for (b=a, sb1=sb; b<tot && sb1->v==sb->v; b++, sb1++) { + newuv[0] += sb1->tface->uv[sb1->tf_sel][0]; + newuv[1] += sb1->tface->uv[sb1->tf_sel][1]; + vtot++; + } + + newuv[0] /= vtot; newuv[1] /= vtot; + + for (b=a, sb1=sb; b<a+vtot; b++, sb1++) { + sb1->tface->uv[sb1->tf_sel][0]= newuv[0]; + sb1->tface->uv[sb1->tf_sel][1]= newuv[1]; + } + } + } else if(mode==1) { + for (a=0, sb=sortblock; a<tot; a+=vtot, sb+=vtot) { + vtot= 0; + for (b=a, sb1=sb; b<tot && sb1->v==sb->v; b++, sb1++) + vtot++; + + for (b=a, sb1=sb; b<a+vtot; b++, sb1++) { + if(sb1->flag & 2) continue; + + newuv[0]= 0; newuv[1]= 0; + vtot2 = 0; + + for (c=b, sb2=sb1; c<a+vtot; c++, sb2++) { + uv = sb2->tface->uv[sb2->tf_sel]; + uv1 = sb1->tface->uv[sb1->tf_sel]; + if (fabs(uv[0]-uv1[0]) < limit[0] && + fabs(uv[1]-uv1[1]) < limit[1]) { + newuv[0] += uv[0]; + newuv[1] += uv[1]; + sb2->flag |= 2; + sb2->flag |= 4; + vtot2++; + } + } + + newuv[0] /= vtot2; newuv[1] /= vtot2; + + for (c=b, sb2=sb1; c<a+vtot; c++, sb2++) { + if(sb2->flag & 4) { + sb2->tface->uv[sb2->tf_sel][0]= newuv[0]; + sb2->tface->uv[sb2->tf_sel][1]= newuv[1]; + sb2->flag &= ~4; + } + } + } + } + } + MEM_freeN(sortblock); + + if(G.sima->flag & SI_BE_SQUARE) be_square_tface_uv(me); + if(G.sima->flag & SI_CLIP_UV) tface_do_clip(); + + allqueue(REDRAWVIEW3D, 0); + scrarea_queue_winredraw(curarea); +} + +void select_linked_tface_uv(void) +{ + MFace *mface; + TFace *tface; + Mesh *me; + char sel; + unsigned int a, b, c, vtot, tot; + float limit[2], *uv, *uv1; + struct uvvertsort *sortblock, *sb, *sb1, *sb2; + + if( is_uv_tface_editing_allowed()==0 ) return; + + me= get_mesh(OBACT); + + setLinkedLimit(limit); + + tot= 0; + mface= me->mface; + for(a=me->totface, tface=me->tface; a>0; a--, tface++, mface++) { + if((tface->flag & TF_SELECT) && mface->v3) { + tot += 3; + if(mface->v4) tot++; + } + } + if(tot==0) return; + + sb= sortblock= MEM_callocN(sizeof(struct uvvertsort)*tot,"sortsellinkuv"); + + mface= me->mface; + for(a=me->totface, tface=me->tface; a>0; a--, tface++, mface++) { + if((tface->flag & TF_SELECT) && mface->v3) { + if(tface->flag & TF_SEL1) sb->flag |= 1; + sb->v= mface->v1; + sb->tface= tface; + sb->tf_sel= 0; + sb++; + if(tface->flag & TF_SEL2) sb->flag |= 1; + sb->v= mface->v2; + sb->tface= tface; + sb->tf_sel= 1; + sb++; + if(tface->flag & TF_SEL3) sb->flag |= 1; + sb->v= mface->v3; + sb->tface= tface; + sb->tf_sel= 2; + sb++; + if(mface->v4) { + if(tface->flag & TF_SEL4) sb->flag |= 1; + sb->v= mface->v4; + sb->tface= tface; + sb->tf_sel= 3; + sb++; + } + } + } + + /* sort by vertex */ + qsort(sortblock, tot, sizeof(struct uvvertsort), compuvvert); + + sel= 1; + while(sel) { + sel= 0; + + /* select all tex vertices that are near a selected tex vertex */ + for (a=0, sb=sortblock; a<tot; a+=vtot, sb+=vtot) { + vtot= 0; + for (b=a, sb1=sb; b<tot && sb1->v==sb->v; b++, sb1++) + vtot++; + for (b=a, sb1=sb; b<a+vtot; b++, sb1++) { + if(sb1->flag & 1) continue; + + for (c=a, sb2=sb; c<a+vtot; c++, sb2++) { + if(!(sb2->flag & 1)) continue; + uv = sb2->tface->uv[sb2->tf_sel]; + uv1 = sb1->tface->uv[sb1->tf_sel]; + if (fabs(uv[0]-uv1[0]) < limit[0] && + fabs(uv[1]-uv1[1]) < limit[1]) { + sb1->flag |= 1; + sel= 1; + break; + } + } + } + } + + /* if one tex vert is selected, select the whole tface */ + for (a=0, sb=sortblock; a<tot; a++, sb++) { + if(sb->flag & 1) { + sb->tface->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); + } + } + + /* sync the flags, one bitflag check is enough */ + for (a=0, sb=sortblock; a<tot; a++, sb++) { + if(sb->tface->flag & TF_SEL1 && !(sb->flag & 1)) { + sb->flag |= 1; + sel= 1; + } + } + } + MEM_freeN(sortblock); + + scrarea_queue_winredraw(curarea); +} + +void unlink_selection(void) +{ + Mesh *me; + TFace *tface; + MFace *mface; + int a; + + if( is_uv_tface_editing_allowed()==0 ) return; + me= get_mesh(OBACT); + + mface= me->mface; + for(a=me->totface, tface= me->tface; a>0; a--, tface++, mface++) { + if(mface->v3 && !(tface->flag & TF_HIDE)) { + if(mface->v4) { + if(~tface->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) + tface->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4); + } else { + if(~tface->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) + tface->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3); + } + } + } + + scrarea_queue_winredraw(curarea); +} + |