Ctrl+RMB in local sticky mode now selects as if in sticky mode. This used to work only in non-sticky mode, but now with local sticky as default, it's nice to have this functionality working there also.
1513 lines
34 KiB
C
1513 lines
34 KiB
C
/**
|
|
* $Id$
|
|
*
|
|
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version. The Blender
|
|
* Foundation also sells licenses for use in proprietary software under
|
|
* the Blender License. See http://www.blender.org/BL/ for information
|
|
* about this.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
* The Original Code is Copyright (C) 2001-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 *****
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#ifndef WIN32
|
|
#include <unistd.h>
|
|
#else
|
|
#include <io.h>
|
|
#endif
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
#include "BLI_blenlib.h"
|
|
#include "BLI_arithb.h"
|
|
|
|
#include "IMB_imbuf_types.h"
|
|
|
|
#include "DNA_mesh_types.h"
|
|
#include "DNA_meshdata_types.h"
|
|
#include "DNA_scene_types.h"
|
|
#include "DNA_screen_types.h"
|
|
#include "DNA_userdef_types.h"
|
|
#include "DNA_space_types.h"
|
|
#include "DNA_image_types.h"
|
|
#include "DNA_object_types.h" // only for uvedit_selectionCB() (struct Object)
|
|
|
|
#include "BKE_colortools.h"
|
|
#include "BKE_depsgraph.h"
|
|
#include "BKE_global.h"
|
|
#include "BKE_mesh.h"
|
|
#include "BKE_displist.h"
|
|
#include "BKE_object.h"
|
|
#include "BKE_utildefines.h"
|
|
|
|
#include "BIF_gl.h"
|
|
#include "BIF_interface.h"
|
|
#include "BIF_screen.h"
|
|
#include "BIF_drawimage.h"
|
|
#include "BIF_editview.h"
|
|
#include "BIF_space.h"
|
|
#include "BIF_editsima.h"
|
|
#include "BIF_toolbox.h"
|
|
#include "BIF_transform.h"
|
|
#include "BIF_mywindow.h"
|
|
|
|
#include "BSE_drawipo.h"
|
|
#include "BSE_edit.h"
|
|
#include "BSE_trans_types.h"
|
|
|
|
#include "BDR_editobject.h"
|
|
#include "BDR_unwrapper.h"
|
|
|
|
#include "BMF_Api.h"
|
|
|
|
#include "blendef.h"
|
|
#include "mydevice.h"
|
|
|
|
/* local prototypes */
|
|
void clever_numbuts_sima(void);
|
|
void sel_uvco_inside_radius(short , TFace *, int , float *, float *, short);
|
|
void uvedit_selectionCB(short , Object *, short *, float ); /* used in edit.c*/
|
|
|
|
void object_uvs_changed(Object *ob)
|
|
{
|
|
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
allqueue(REDRAWIMAGE, 0);
|
|
}
|
|
|
|
void object_tface_flags_changed(Object *ob, int updateButtons)
|
|
{
|
|
if (updateButtons) allqueue(REDRAWBUTSEDIT, 0);
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
allqueue(REDRAWIMAGE, 0);
|
|
}
|
|
|
|
int is_uv_tface_editing_allowed_silent(void)
|
|
{
|
|
Mesh *me;
|
|
|
|
if(G.obedit) return 0;
|
|
if(G.sima->mode!=SI_TEXTURE) return 0;
|
|
if(!(G.f & G_FACESELECT)) return 0;
|
|
me= get_mesh(OBACT);
|
|
if(me==0 || me->tface==0) return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
int is_uv_tface_editing_allowed(void)
|
|
{
|
|
if(G.obedit) error("Unable to perform action in Edit Mode");
|
|
|
|
return is_uv_tface_editing_allowed_silent();
|
|
}
|
|
|
|
void get_connected_limit_tface_uv(float *limit)
|
|
{
|
|
if(G.sima->image && G.sima->image->ibuf && G.sima->image->ibuf->x > 0 &&
|
|
G.sima->image->ibuf->y > 0) {
|
|
limit[0]= 0.05/(float)G.sima->image->ibuf->x;
|
|
limit[1]= 0.05/(float)G.sima->image->ibuf->y;
|
|
}
|
|
else
|
|
limit[0]= limit[1]= 0.05/256.0;
|
|
}
|
|
|
|
void clever_numbuts_sima(void)
|
|
{
|
|
float ocent[2], cent[2]= {0.0, 0.0};
|
|
int imx, imy;
|
|
int i, nactive= 0;
|
|
Mesh *me;
|
|
|
|
if( is_uv_tface_editing_allowed()==0 ) return;
|
|
me= get_mesh(OBACT);
|
|
|
|
if (G.sima->image && G.sima->image->ibuf) {
|
|
imx= G.sima->image->ibuf->x;
|
|
imy= G.sima->image->ibuf->y;
|
|
} else
|
|
imx= imy= 256;
|
|
|
|
for (i=0; i<me->totface; i++) {
|
|
MFace *mf= &((MFace*) me->mface)[i];
|
|
TFace *tf= &((TFace*) me->tface)[i];
|
|
|
|
if (!(tf->flag & TF_SELECT))
|
|
continue;
|
|
|
|
if (tf->flag & TF_SEL1) {
|
|
cent[0]+= tf->uv[0][0];
|
|
cent[1]+= tf->uv[0][1];
|
|
nactive++;
|
|
}
|
|
if (tf->flag & TF_SEL2) {
|
|
cent[0]+= tf->uv[1][0];
|
|
cent[1]+= tf->uv[1][1];
|
|
nactive++;
|
|
}
|
|
if (tf->flag & TF_SEL3) {
|
|
cent[0]+= tf->uv[2][0];
|
|
cent[1]+= tf->uv[2][1];
|
|
nactive++;
|
|
}
|
|
if (mf->v4 && (tf->flag & TF_SEL4)) {
|
|
cent[0]+= tf->uv[3][0];
|
|
cent[1]+= tf->uv[3][1];
|
|
nactive++;
|
|
}
|
|
}
|
|
|
|
if (nactive) {
|
|
cent[0]= (cent[0]*imx)/nactive;
|
|
cent[1]= (cent[1]*imy)/nactive;
|
|
|
|
add_numbut(0, NUM|FLO, "LocX:", -imx*20, imx*20, ¢[0], NULL);
|
|
add_numbut(1, NUM|FLO, "LocY:", -imy*20, imy*20, ¢[1], NULL);
|
|
|
|
ocent[0]= cent[0];
|
|
ocent[1]= cent[1];
|
|
if (do_clever_numbuts((nactive==1)?"Active Vertex":"Selected Center", 2, REDRAW)) {
|
|
float delta[2];
|
|
|
|
delta[0]= (cent[0]-ocent[0])/imx;
|
|
delta[1]= (cent[1]-ocent[1])/imy;
|
|
|
|
for (i=0; i<me->totface; i++) {
|
|
MFace *mf= &((MFace*) me->mface)[i];
|
|
TFace *tf= &((TFace*) me->tface)[i];
|
|
|
|
if (!(tf->flag & TF_SELECT))
|
|
continue;
|
|
|
|
if (tf->flag & TF_SEL1) {
|
|
tf->uv[0][0]+= delta[0];
|
|
tf->uv[0][1]+= delta[1];
|
|
}
|
|
if (tf->flag & TF_SEL2) {
|
|
tf->uv[1][0]+= delta[0];
|
|
tf->uv[1][1]+= delta[1];
|
|
}
|
|
if (tf->flag & TF_SEL3) {
|
|
tf->uv[2][0]+= delta[0];
|
|
tf->uv[2][1]+= delta[1];
|
|
}
|
|
if (mf->v4 && (tf->flag & TF_SEL4)) {
|
|
tf->uv[3][0]+= delta[0];
|
|
tf->uv[3][1]+= delta[1];
|
|
}
|
|
}
|
|
|
|
object_uvs_changed(OBACT);
|
|
}
|
|
}
|
|
}
|
|
|
|
void be_square_tface_uv(Mesh *me)
|
|
{
|
|
TFace *tface;
|
|
MFace *mface;
|
|
int a;
|
|
|
|
/* if 1 vertex selected: doit (with the selected vertex) */
|
|
mface= (MFace*)me->mface;
|
|
tface= (TFace*)me->tface;
|
|
for(a=me->totface; a>0; a--, tface++, mface++) {
|
|
if(mface->v4) {
|
|
if(tface->flag & TF_SELECT) {
|
|
if(tface->flag & TF_SEL1) {
|
|
if( tface->uv[1][0] == tface->uv[2][0] ) {
|
|
tface->uv[1][1]= tface->uv[0][1];
|
|
tface->uv[3][0]= tface->uv[0][0];
|
|
}
|
|
else {
|
|
tface->uv[1][0]= tface->uv[0][0];
|
|
tface->uv[3][1]= tface->uv[0][1];
|
|
}
|
|
|
|
}
|
|
if(tface->flag & TF_SEL2) {
|
|
if( tface->uv[2][1] == tface->uv[3][1] ) {
|
|
tface->uv[2][0]= tface->uv[1][0];
|
|
tface->uv[0][1]= tface->uv[1][1];
|
|
}
|
|
else {
|
|
tface->uv[2][1]= tface->uv[1][1];
|
|
tface->uv[0][0]= tface->uv[1][0];
|
|
}
|
|
|
|
}
|
|
if(tface->flag & TF_SEL3) {
|
|
if( tface->uv[3][0] == tface->uv[0][0] ) {
|
|
tface->uv[3][1]= tface->uv[2][1];
|
|
tface->uv[1][0]= tface->uv[2][0];
|
|
}
|
|
else {
|
|
tface->uv[3][0]= tface->uv[2][0];
|
|
tface->uv[1][1]= tface->uv[2][1];
|
|
}
|
|
}
|
|
if(tface->flag & TF_SEL4) {
|
|
if( tface->uv[0][1] == tface->uv[1][1] ) {
|
|
tface->uv[0][0]= tface->uv[3][0];
|
|
tface->uv[2][1]= tface->uv[3][1];
|
|
}
|
|
else {
|
|
tface->uv[0][1]= tface->uv[3][1];
|
|
tface->uv[2][0]= tface->uv[3][0];
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void transform_aspect_ratio_tface_uv(float *aspx, float *aspy)
|
|
{
|
|
int w, h;
|
|
|
|
transform_width_height_tface_uv(&w, &h);
|
|
*aspx= (float)w/256.0f;
|
|
*aspy= (float)h/256.0f;
|
|
}
|
|
|
|
void transform_width_height_tface_uv(int *width, int *height)
|
|
{
|
|
if(G.sima->image && G.sima->image->ibuf) {
|
|
*width= G.sima->image->ibuf->x;
|
|
*height= G.sima->image->ibuf->y;
|
|
}
|
|
else {
|
|
*width= 256;
|
|
*height= 256;
|
|
}
|
|
}
|
|
|
|
void mirror_tface_uv(char mirroraxis)
|
|
{
|
|
if (mirroraxis == 'x')
|
|
Mirror(1); /* global x */
|
|
else if (mirroraxis == 'y')
|
|
Mirror(2); /* global y */
|
|
}
|
|
|
|
void mirrormenu_tface_uv(void)
|
|
{
|
|
short mode= 0;
|
|
|
|
if( is_uv_tface_editing_allowed()==0 ) return;
|
|
|
|
mode= pupmenu("Mirror%t|X Axis%x1|Y Axis%x2|");
|
|
|
|
if(mode==-1) return;
|
|
|
|
if(mode==1) mirror_tface_uv('x');
|
|
else if(mode==2) mirror_tface_uv('y');
|
|
|
|
BIF_undo_push("Mirror UV");
|
|
}
|
|
|
|
void weld_align_tface_uv(char tool)
|
|
{
|
|
MFace *mface;
|
|
TFace *tface;
|
|
Mesh *me;
|
|
float min[2], max[2], cent[2];
|
|
int a;
|
|
|
|
if( is_uv_tface_editing_allowed()==0 ) return;
|
|
me= get_mesh(OBACT);
|
|
|
|
if (!minmax_tface_uv(min, max))
|
|
return;
|
|
|
|
cent[0]= (min[0]+max[0])/2.0;
|
|
cent[1]= (min[1]+max[1])/2.0;
|
|
|
|
if(tool == 'x' || tool == 'w') {
|
|
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)
|
|
tface->uv[0][0]= cent[0];
|
|
if(tface->flag & TF_SEL2)
|
|
tface->uv[1][0]= cent[0];
|
|
if(tface->flag & TF_SEL3)
|
|
tface->uv[2][0]= cent[0];
|
|
if(mface->v4 && (tface->flag & TF_SEL4))
|
|
tface->uv[3][0]= cent[0];
|
|
}
|
|
}
|
|
}
|
|
|
|
if(tool == 'y' || tool == 'w') {
|
|
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)
|
|
tface->uv[0][1]= cent[1];
|
|
if(tface->flag & TF_SEL2)
|
|
tface->uv[1][1]= cent[1];
|
|
if(tface->flag & TF_SEL3)
|
|
tface->uv[2][1]= cent[1];
|
|
if(mface->v4 && (tface->flag & TF_SEL4))
|
|
tface->uv[3][1]= cent[1];
|
|
}
|
|
}
|
|
}
|
|
|
|
object_uvs_changed(OBACT);
|
|
}
|
|
|
|
void weld_align_menu_tface_uv(void)
|
|
{
|
|
short mode= 0;
|
|
|
|
if( is_uv_tface_editing_allowed()==0 ) return;
|
|
|
|
mode= pupmenu("Weld/Align%t|Weld%x1|Align X%x2|Align Y%x3|");
|
|
|
|
if(mode==-1) return;
|
|
|
|
if(mode==1) weld_align_tface_uv('w');
|
|
else if(mode==2) weld_align_tface_uv('x');
|
|
else if(mode==3) weld_align_tface_uv('y');
|
|
|
|
if(mode==1) BIF_undo_push("Weld UV");
|
|
else if(mode==2 || mode==3) BIF_undo_push("Align UV");
|
|
}
|
|
|
|
void select_swap_tface_uv(void)
|
|
{
|
|
Mesh *me;
|
|
TFace *tface;
|
|
MFace *mface;
|
|
int a, sel=0;
|
|
|
|
if( is_uv_tface_editing_allowed()==0 ) return;
|
|
me= get_mesh(OBACT);
|
|
|
|
for(a=me->totface, tface= me->tface; a>0; a--, tface++) {
|
|
if(tface->flag & TF_SELECT) {
|
|
if(tface->flag & (TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4)) {
|
|
sel= 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
mface= me->mface;
|
|
for(a=me->totface, tface= me->tface; a>0; a--, tface++, mface++) {
|
|
if(tface->flag & TF_SELECT) {
|
|
if(mface->v4) {
|
|
if(sel) tface->flag &= ~(TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
|
|
else tface->flag |= (TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
|
|
}
|
|
else {
|
|
if(sel) tface->flag &= ~(TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
|
|
else tface->flag |= (TF_SEL1+TF_SEL2+TF_SEL3);
|
|
}
|
|
}
|
|
}
|
|
|
|
BIF_undo_push("Select swap UV");
|
|
|
|
allqueue(REDRAWIMAGE, 0);
|
|
}
|
|
|
|
static int msel_hit(float *limit, unsigned int *hitarray, unsigned int vertexid, float **uv, float *uv2, int sticky)
|
|
{
|
|
int i;
|
|
for(i=0; i< 4; i++) {
|
|
if(hitarray[i] == vertexid) {
|
|
if(sticky == 2) {
|
|
if(fabs(uv[i][0]-uv2[0]) < limit[0] &&
|
|
fabs(uv[i][1]-uv2[1]) < limit[1])
|
|
return 1;
|
|
}
|
|
else return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void find_nearest_tface(TFace **nearesttf, MFace **nearestmf)
|
|
{
|
|
Mesh *me;
|
|
TFace *tf;
|
|
MFace *mf;
|
|
int a, i, nverts, mindist, dist, fcenter[2], uval[2];
|
|
short mval[2];
|
|
|
|
getmouseco_areawin(mval);
|
|
|
|
mindist= 0x7FFFFFF;
|
|
*nearesttf= NULL;
|
|
*nearestmf= NULL;
|
|
|
|
me= get_mesh(OBACT);
|
|
mf= (MFace*)me->mface;
|
|
tf= (TFace*)me->tface;
|
|
|
|
for(a=me->totface; a>0; a--, tf++, mf++) {
|
|
if(tf->flag & TF_SELECT) {
|
|
|
|
fcenter[0]= fcenter[1]= 0;
|
|
nverts= mf->v4? 4: 3;
|
|
for(i=0; i<nverts; i++) {
|
|
uvco_to_areaco_noclip(tf->uv[i], uval);
|
|
fcenter[0] += uval[0];
|
|
fcenter[1] += uval[1];
|
|
}
|
|
|
|
fcenter[0] /= nverts;
|
|
fcenter[1] /= nverts;
|
|
|
|
dist= abs(mval[0]- fcenter[0])+ abs(mval[1]- fcenter[1]);
|
|
if (dist < mindist) {
|
|
*nearesttf= tf;
|
|
*nearestmf= mf;
|
|
mindist= dist;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static int nearest_uv_between(TFace *tf, int nverts, int id, short *mval, int *uval)
|
|
{
|
|
float m[3], v1[3], v2[3], c1, c2;
|
|
int id1, id2;
|
|
|
|
id1= (id+nverts-1)%nverts;
|
|
id2= (id+nverts+1)%nverts;
|
|
|
|
m[0] = (float)(mval[0]-uval[0]);
|
|
m[1] = (float)(mval[1]-uval[1]);
|
|
Vec2Subf(v1, tf->uv[id1], tf->uv[id]);
|
|
Vec2Subf(v2, tf->uv[id2], tf->uv[id]);
|
|
|
|
/* m and v2 on same side of v-v1? */
|
|
c1= v1[0]*m[1] - v1[1]*m[0];
|
|
c2= v1[0]*v2[1] - v1[1]*v2[0];
|
|
|
|
if (c1*c2 < 0.0f)
|
|
return 0;
|
|
|
|
/* m and v1 on same side of v-v2? */
|
|
c1= v2[0]*m[1] - v2[1]*m[0];
|
|
c2= v2[0]*v1[1] - v2[1]*v1[0];
|
|
|
|
return (c1*c2 >= 0.0f);
|
|
}
|
|
|
|
static void find_nearest_uv(TFace **nearesttf, unsigned int *nearestv, int *nearestuv)
|
|
{
|
|
Mesh *me;
|
|
TFace *tf;
|
|
MFace *mf;
|
|
int a, i, nverts, mindist, dist, uval[2];
|
|
short mval[2];
|
|
|
|
getmouseco_areawin(mval);
|
|
|
|
mindist= 0x7FFFFFF;
|
|
*nearesttf= NULL;
|
|
|
|
me= get_mesh(OBACT);
|
|
mf= (MFace*)me->mface;
|
|
tf= (TFace*)me->tface;
|
|
|
|
for(a=me->totface; a>0; a--, tf++, mf++) {
|
|
if(tf->flag & TF_SELECT) {
|
|
|
|
nverts= mf->v4? 4: 3;
|
|
for(i=0; i<nverts; i++) {
|
|
uvco_to_areaco_noclip(tf->uv[i], uval);
|
|
dist= abs(mval[0]-uval[0]) + abs(mval[1]-uval[1]);
|
|
|
|
if(tf->flag & TF_SEL_MASK(i))
|
|
dist += 5;
|
|
|
|
if(dist<=mindist) {
|
|
if(dist==mindist)
|
|
if (!nearest_uv_between(tf, nverts, i, mval, uval))
|
|
continue;
|
|
|
|
mindist= dist;
|
|
|
|
*nearesttf= tf;
|
|
*nearestuv= i;
|
|
|
|
if (i==0) *nearestv= mf->v1;
|
|
else if (i==1) *nearestv= mf->v2;
|
|
else if (i==2) *nearestv= mf->v3;
|
|
else *nearestv= mf->v4;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void mouse_select_sima(void)
|
|
{
|
|
Mesh *me;
|
|
TFace *tf, *nearesttf;
|
|
MFace *mf, *nearestmf=NULL;
|
|
int a, selectsticky, sticky, actface, nearestuv, i;
|
|
unsigned int hitv[4], nearestv;
|
|
float *hituv[4], limit[2];
|
|
|
|
if( is_uv_tface_editing_allowed()==0 ) return;
|
|
me= get_mesh(OBACT);
|
|
|
|
get_connected_limit_tface_uv(limit);
|
|
actface= (G.qual & LR_ALTKEY || G.sima->flag & SI_SELACTFACE);
|
|
|
|
if(G.qual & LR_CTRLKEY) {
|
|
if(G.sima->flag & SI_STICKYUVS) sticky= 0;
|
|
else sticky= 1;
|
|
}
|
|
else {
|
|
if(G.sima->flag & SI_STICKYUVS) sticky= 1;
|
|
else if(G.sima->flag & SI_LOCALSTICKY) sticky= 2;
|
|
else sticky= 0;
|
|
}
|
|
|
|
if(actface) {
|
|
find_nearest_tface(&nearesttf, &nearestmf);
|
|
if(nearesttf==NULL)
|
|
return;
|
|
|
|
nearesttf->flag |= TF_ACTIVE;
|
|
|
|
for (i=0; i<4; i++)
|
|
hituv[i]= nearesttf->uv[i];
|
|
|
|
hitv[0]= nearestmf->v1;
|
|
hitv[1]= nearestmf->v2;
|
|
hitv[2]= nearestmf->v3;
|
|
hitv[3]= nearestmf->v4? nearestmf->v4: 0xFFFFFFFF;
|
|
}
|
|
else {
|
|
find_nearest_uv(&nearesttf, &nearestv, &nearestuv);
|
|
if(nearesttf==NULL)
|
|
return;
|
|
|
|
if(sticky) {
|
|
for(i=0; i<4; i++)
|
|
hitv[i]= 0xFFFFFFFF;
|
|
hitv[nearestuv]= nearestv;
|
|
hituv[nearestuv]= nearesttf->uv[nearestuv];
|
|
}
|
|
}
|
|
|
|
if(G.qual & LR_SHIFTKEY) {
|
|
/* (de)select face */
|
|
if(actface) {
|
|
if(!(~nearesttf->flag & (TF_SEL1|TF_SEL2|TF_SEL3))
|
|
&& (!nearestmf->v4 || nearesttf->flag & TF_SEL4)) {
|
|
nearesttf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
|
|
selectsticky= 0;
|
|
}
|
|
else {
|
|
nearesttf->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4;
|
|
selectsticky= 1;
|
|
}
|
|
}
|
|
/* (de)select uv node */
|
|
else {
|
|
if(nearesttf->flag & TF_SEL_MASK(nearestuv)) {
|
|
nearesttf->flag &= ~TF_SEL_MASK(nearestuv);
|
|
selectsticky= 0;
|
|
}
|
|
else {
|
|
nearesttf->flag |= TF_SEL_MASK(nearestuv);
|
|
selectsticky= 1;
|
|
}
|
|
}
|
|
|
|
/* (de)select sticky uv nodes */
|
|
if(sticky || actface) {
|
|
mf= (MFace*)me->mface;
|
|
tf= (TFace*)me->tface;
|
|
/* deselect */
|
|
if(selectsticky==0) {
|
|
for(a=me->totface; a>0; a--, tf++, mf++) {
|
|
if(!(tf->flag & TF_SELECT)) continue;
|
|
if(nearesttf && tf!=nearesttf) tf->flag &=~ TF_ACTIVE;
|
|
if (!sticky) continue;
|
|
|
|
if(msel_hit(limit, hitv, mf->v1, hituv, tf->uv[0], sticky))
|
|
tf->flag &= ~TF_SEL1;
|
|
if(msel_hit(limit, hitv, mf->v2, hituv, tf->uv[1], sticky))
|
|
tf->flag &= ~TF_SEL2;
|
|
if(msel_hit(limit, hitv, mf->v3, hituv, tf->uv[2], sticky))
|
|
tf->flag &= ~TF_SEL3;
|
|
if (mf->v4)
|
|
if(msel_hit(limit, hitv, mf->v4, hituv, tf->uv[3], sticky))
|
|
tf->flag &= ~TF_SEL4;
|
|
}
|
|
}
|
|
/* select */
|
|
else {
|
|
for(a=me->totface; a>0; a--, tf++, mf++) {
|
|
if(!(tf->flag & TF_SELECT)) continue;
|
|
if(nearesttf && tf!=nearesttf)
|
|
tf->flag &=~ TF_ACTIVE;
|
|
if (!sticky) continue;
|
|
|
|
if(msel_hit(limit, hitv, mf->v1, hituv, tf->uv[0], sticky))
|
|
tf->flag |= TF_SEL1;
|
|
if(msel_hit(limit, hitv, mf->v2, hituv, tf->uv[1], sticky))
|
|
tf->flag |= TF_SEL2;
|
|
if(msel_hit(limit, hitv, mf->v3, hituv, tf->uv[2], sticky))
|
|
tf->flag |= TF_SEL3;
|
|
if (mf->v4)
|
|
if(msel_hit(limit, hitv, mf->v4, hituv, tf->uv[3], sticky))
|
|
tf->flag |= TF_SEL4;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
/* select face and deselect other faces */
|
|
if(actface) {
|
|
mf= (MFace*)me->mface;
|
|
tf= (TFace*)me->tface;
|
|
for(a=me->totface; a>0; a--, tf++, mf++) {
|
|
tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
|
|
if(nearesttf && tf!=nearesttf)
|
|
tf->flag &= ~TF_ACTIVE;
|
|
}
|
|
if(nearesttf)
|
|
nearesttf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
|
|
}
|
|
|
|
/* deselect uvs, and select sticky uvs */
|
|
mf= (MFace*)me->mface;
|
|
tf= (TFace*)me->tface;
|
|
for(a=me->totface; a>0; a--, tf++, mf++) {
|
|
if(tf->flag & TF_SELECT) {
|
|
if(!actface) tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
|
|
if(!sticky) continue;
|
|
|
|
if(msel_hit(limit, hitv, mf->v1, hituv, tf->uv[0], sticky))
|
|
tf->flag |= TF_SEL1;
|
|
if(msel_hit(limit, hitv, mf->v2, hituv, tf->uv[1], sticky))
|
|
tf->flag |= TF_SEL2;
|
|
if(msel_hit(limit, hitv, mf->v3, hituv, tf->uv[2], sticky))
|
|
tf->flag |= TF_SEL3;
|
|
if(mf->v4)
|
|
if(msel_hit(limit, hitv, mf->v4, hituv, tf->uv[3], sticky))
|
|
tf->flag |= TF_SEL4;
|
|
}
|
|
}
|
|
|
|
if(!actface)
|
|
nearesttf->flag |= TF_SEL_MASK(nearestuv);
|
|
}
|
|
|
|
force_draw(1);
|
|
|
|
BIF_undo_push("Select UV");
|
|
rightmouse_transform();
|
|
}
|
|
|
|
void borderselect_sima(short whichuvs)
|
|
{
|
|
Mesh *me;
|
|
TFace *tface;
|
|
MFace *mface;
|
|
rcti rect;
|
|
rctf rectf;
|
|
int a, val;
|
|
short mval[2];
|
|
|
|
if( is_uv_tface_editing_allowed()==0 ) return;
|
|
me= get_mesh(OBACT);
|
|
|
|
val= get_border(&rect, 3);
|
|
|
|
if(val) {
|
|
mval[0]= rect.xmin;
|
|
mval[1]= rect.ymin;
|
|
areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
|
|
mval[0]= rect.xmax;
|
|
mval[1]= rect.ymax;
|
|
areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
|
|
|
|
mface= me->mface;
|
|
for(a=me->totface, tface= me->tface; a>0; a--, tface++, mface++) {
|
|
|
|
if(tface->flag & TF_SELECT) {
|
|
|
|
if (whichuvs == UV_SELECT_ALL) {
|
|
|
|
if(BLI_in_rctf(&rectf, (float)tface->uv[0][0], (float)tface->uv[0][1])) {
|
|
if(val==LEFTMOUSE) tface->flag |= TF_SEL1;
|
|
else tface->flag &= ~TF_SEL1;
|
|
}
|
|
if(BLI_in_rctf(&rectf, (float)tface->uv[1][0], (float)tface->uv[1][1])) {
|
|
if(val==LEFTMOUSE) tface->flag |= TF_SEL2;
|
|
else tface->flag &= ~TF_SEL2;
|
|
}
|
|
if(BLI_in_rctf(&rectf, (float)tface->uv[2][0], (float)tface->uv[2][1])) {
|
|
if(val==LEFTMOUSE) tface->flag |= TF_SEL3;
|
|
else tface->flag &= ~TF_SEL3;
|
|
}
|
|
if(mface->v4 && BLI_in_rctf(&rectf, (float)tface->uv[3][0], (float)tface->uv[3][1])) {
|
|
if(val==LEFTMOUSE) tface->flag |= TF_SEL4;
|
|
else tface->flag &= ~TF_SEL4;
|
|
}
|
|
} else if (whichuvs == UV_SELECT_PINNED) {
|
|
if ((tface->unwrap & TF_PIN1) &&
|
|
BLI_in_rctf(&rectf, (float)tface->uv[0][0], (float)tface->uv[0][1])) {
|
|
|
|
if(val==LEFTMOUSE) tface->flag |= TF_SEL1;
|
|
else tface->flag &= ~TF_SEL1;
|
|
}
|
|
if ((tface->unwrap & TF_PIN2) &&
|
|
BLI_in_rctf(&rectf, (float)tface->uv[1][0], (float)tface->uv[1][1])) {
|
|
|
|
if(val==LEFTMOUSE) tface->flag |= TF_SEL2;
|
|
else tface->flag &= ~TF_SEL2;
|
|
}
|
|
if ((tface->unwrap & TF_PIN3) &&
|
|
BLI_in_rctf(&rectf, (float)tface->uv[2][0], (float)tface->uv[2][1])) {
|
|
|
|
if(val==LEFTMOUSE) tface->flag |= TF_SEL3;
|
|
else tface->flag &= ~TF_SEL3;
|
|
}
|
|
if ((mface->v4) && (tface->unwrap & TF_PIN4) && BLI_in_rctf(&rectf, (float)tface->uv[3][0], (float)tface->uv[3][1])) {
|
|
if(val==LEFTMOUSE) tface->flag |= TF_SEL4;
|
|
else tface->flag &= ~TF_SEL4;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
BIF_undo_push("Border select UV");
|
|
scrarea_queue_winredraw(curarea);
|
|
}
|
|
}
|
|
|
|
/** This is an ugly function to set the Tface selection flags depending
|
|
* on whether its UV coordinates are inside the normalized
|
|
* area with radius rad and offset offset. These coordinates must be
|
|
* normalized to 1.0
|
|
* Just for readability...
|
|
*/
|
|
|
|
void sel_uvco_inside_radius(short sel, TFace *tface, int index, float *offset, float *ell, short select_mask)
|
|
{
|
|
// normalized ellipse: ell[0] = scaleX,
|
|
// [1] = scaleY
|
|
|
|
float *uv = tface->uv[index];
|
|
float x, y, r2;
|
|
|
|
x = (uv[0] - offset[0]) * ell[0];
|
|
y = (uv[1] - offset[1]) * ell[1];
|
|
|
|
r2 = x * x + y * y;
|
|
if (r2 < 1.0) {
|
|
if (sel == LEFTMOUSE) tface->flag |= select_mask;
|
|
else tface->flag &= ~select_mask;
|
|
}
|
|
}
|
|
|
|
// see below:
|
|
/** gets image dimensions of the 2D view 'v' */
|
|
static void getSpaceImageDimension(SpaceImage *sima, float *xy)
|
|
{
|
|
Image *img = sima->image;
|
|
float z;
|
|
|
|
z = sima->zoom;
|
|
|
|
if (img && img->ibuf) {
|
|
xy[0] = img->ibuf->x * z;
|
|
xy[1] = img->ibuf->y * z;
|
|
} else {
|
|
xy[0] = 256 * z;
|
|
xy[1] = 256 * z;
|
|
}
|
|
}
|
|
|
|
/** Callback function called by circle_selectCB to enable
|
|
* brush select in UV editor.
|
|
*/
|
|
|
|
void uvedit_selectionCB(short selecting, Object *editobj, short *mval, float rad)
|
|
{
|
|
float offset[2];
|
|
Mesh *me;
|
|
MFace *mface;
|
|
TFace *tface;
|
|
int i;
|
|
|
|
float ellipse[2]; // we need to deal with ellipses, as
|
|
// non square textures require for circle
|
|
// selection. this ellipse is normalized; r = 1.0
|
|
|
|
me = get_mesh(editobj);
|
|
|
|
getSpaceImageDimension(curarea->spacedata.first, ellipse);
|
|
ellipse[0] /= rad;
|
|
ellipse[1] /= rad;
|
|
|
|
areamouseco_to_ipoco(G.v2d, mval, &offset[0], &offset[1]);
|
|
|
|
mface= me->mface;
|
|
tface= me->tface;
|
|
|
|
if (selecting) {
|
|
for(i = 0; i < me->totface; i++) {
|
|
sel_uvco_inside_radius(selecting, tface, 0, offset, ellipse, TF_SEL1);
|
|
sel_uvco_inside_radius(selecting, tface, 1, offset, ellipse, TF_SEL2);
|
|
sel_uvco_inside_radius(selecting, tface, 2, offset, ellipse, TF_SEL3);
|
|
if (mface->v4)
|
|
sel_uvco_inside_radius(selecting, tface, 3, offset, ellipse, TF_SEL4);
|
|
|
|
tface++; mface++;
|
|
|
|
}
|
|
|
|
if(G.f & G_DRAWFACES) { /* full redraw only if necessary */
|
|
draw_sel_circle(0, 0, 0, 0, 0); /* signal */
|
|
force_draw(0);
|
|
}
|
|
else { /* force_draw() is no good here... */
|
|
glDrawBuffer(GL_FRONT);
|
|
draw_tfaces();
|
|
glDrawBuffer(GL_BACK);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void mouseco_to_curtile(void)
|
|
{
|
|
float fx, fy;
|
|
short mval[2];
|
|
|
|
if( is_uv_tface_editing_allowed()==0) return;
|
|
|
|
if(G.sima->image && G.sima->image->tpageflag & IMA_TILES) {
|
|
|
|
G.sima->flag |= SI_EDITTILE;
|
|
|
|
while(get_mbut()&L_MOUSE) {
|
|
|
|
calc_image_view(G.sima, 'f');
|
|
|
|
getmouseco_areawin(mval);
|
|
areamouseco_to_ipoco(G.v2d, mval, &fx, &fy);
|
|
|
|
if(fx>=0.0 && fy>=0.0 && fx<1.0 && fy<1.0) {
|
|
|
|
fx= (fx)*G.sima->image->xrep;
|
|
fy= (fy)*G.sima->image->yrep;
|
|
|
|
mval[0]= fx;
|
|
mval[1]= fy;
|
|
|
|
G.sima->curtile= mval[1]*G.sima->image->xrep + mval[0];
|
|
}
|
|
|
|
scrarea_do_windraw(curarea);
|
|
screen_swapbuffers();
|
|
}
|
|
|
|
G.sima->flag &= ~SI_EDITTILE;
|
|
|
|
image_changed(G.sima, 1);
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
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(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(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;
|
|
}
|
|
}
|
|
}
|
|
|
|
BIF_undo_push("Hide UV");
|
|
|
|
object_tface_flags_changed(OBACT, 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(!(tface->flag & TF_HIDE))
|
|
if(!(tface->flag & TF_SELECT))
|
|
tface->flag |= (TF_SELECT|TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
|
|
|
|
BIF_undo_push("Reveal UV");
|
|
|
|
object_tface_flags_changed(OBACT, 0);
|
|
}
|
|
|
|
void stitch_uv_tface(int mode)
|
|
{
|
|
Mesh *me;
|
|
TFace *tf;
|
|
int a, vtot;
|
|
float newuv[2], limit[2];
|
|
UvMapVert *vlist, *iterv, *v;
|
|
UvVertMap *vmap;
|
|
|
|
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);
|
|
tf= me->tface;
|
|
|
|
vmap= make_uv_vert_map(me->mface, tf, me->totface, me->totvert, 1, limit);
|
|
if(vmap == NULL)
|
|
return;
|
|
|
|
if(mode==0) {
|
|
for(a=0; a<me->totvert; a++) {
|
|
v = get_uv_map_vert(vmap, a);
|
|
|
|
if(v == NULL)
|
|
continue;
|
|
|
|
newuv[0]= 0; newuv[1]= 0;
|
|
vtot= 0;
|
|
|
|
for(iterv=v; iterv; iterv=iterv->next) {
|
|
if (tf[iterv->f].flag & TF_SEL_MASK(iterv->tfindex)) {
|
|
newuv[0] += tf[iterv->f].uv[iterv->tfindex][0];
|
|
newuv[1] += tf[iterv->f].uv[iterv->tfindex][1];
|
|
vtot++;
|
|
}
|
|
}
|
|
|
|
if (vtot > 1) {
|
|
newuv[0] /= vtot; newuv[1] /= vtot;
|
|
|
|
for(iterv=v; iterv; iterv=iterv->next) {
|
|
if (tf[iterv->f].flag & TF_SEL_MASK(iterv->tfindex)) {
|
|
tf[iterv->f].uv[iterv->tfindex][0]= newuv[0];
|
|
tf[iterv->f].uv[iterv->tfindex][1]= newuv[1];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else if(mode==1) {
|
|
for(a=0; a<me->totvert; a++) {
|
|
vlist= get_uv_map_vert(vmap, a);
|
|
|
|
while(vlist) {
|
|
newuv[0]= 0; newuv[1]= 0;
|
|
vtot= 0;
|
|
|
|
for(iterv=vlist; iterv; iterv=iterv->next) {
|
|
if((iterv != vlist) && iterv->separate)
|
|
break;
|
|
if (tf[iterv->f].flag & TF_SEL_MASK(iterv->tfindex)) {
|
|
newuv[0] += tf[iterv->f].uv[iterv->tfindex][0];
|
|
newuv[1] += tf[iterv->f].uv[iterv->tfindex][1];
|
|
vtot++;
|
|
}
|
|
}
|
|
|
|
if (vtot > 1) {
|
|
newuv[0] /= vtot; newuv[1] /= vtot;
|
|
|
|
for(iterv=vlist; iterv; iterv=iterv->next) {
|
|
if((iterv != vlist) && iterv->separate)
|
|
break;
|
|
if (tf[iterv->f].flag & TF_SEL_MASK(iterv->tfindex)) {
|
|
tf[iterv->f].uv[iterv->tfindex][0]= newuv[0];
|
|
tf[iterv->f].uv[iterv->tfindex][1]= newuv[1];
|
|
}
|
|
}
|
|
}
|
|
|
|
vlist= iterv;
|
|
}
|
|
}
|
|
}
|
|
|
|
free_uv_vert_map(vmap);
|
|
|
|
if(G.sima->flag & SI_BE_SQUARE) be_square_tface_uv(me);
|
|
|
|
BIF_undo_push("Stitch UV");
|
|
|
|
object_uvs_changed(OBACT);
|
|
}
|
|
|
|
void select_linked_tface_uv(int mode)
|
|
{
|
|
Mesh *me;
|
|
MFace *mf;
|
|
TFace *tf, *nearesttf=NULL;
|
|
UvVertMap *vmap;
|
|
UvMapVert *vlist, *iterv, *startv;
|
|
unsigned int *stack, stacksize= 0, nearestv;
|
|
char *flag;
|
|
int a, nearestuv, i, nverts;
|
|
float limit[2];
|
|
|
|
if(is_uv_tface_editing_allowed()==0)
|
|
return;
|
|
|
|
me= get_mesh(OBACT);
|
|
|
|
if (mode == 2) {
|
|
nearesttf= NULL;
|
|
nearestuv= 0;
|
|
}
|
|
if (mode!=2) {
|
|
find_nearest_uv(&nearesttf, &nearestv, &nearestuv);
|
|
if(nearesttf==NULL)
|
|
return;
|
|
}
|
|
|
|
get_connected_limit_tface_uv(limit);
|
|
vmap= make_uv_vert_map(me->mface, me->tface, me->totface, me->totvert, 1, limit);
|
|
if(vmap == NULL)
|
|
return;
|
|
|
|
stack= MEM_mallocN(sizeof(*stack)*me->totface, "UvLinkStack");
|
|
flag= MEM_callocN(sizeof(*flag)*me->totface, "UvLinkFlag");
|
|
|
|
if (mode == 2) {
|
|
tf= me->tface;
|
|
for(a=0; a<me->totface; a++, tf++)
|
|
if(!(tf->flag & TF_HIDE) && (tf->flag & TF_SELECT))
|
|
if(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) {
|
|
stack[stacksize]= a;
|
|
stacksize++;
|
|
flag[a]= 1;
|
|
}
|
|
}
|
|
else {
|
|
tf= me->tface;
|
|
for(a=0; a<me->totface; a++, tf++)
|
|
if(tf == nearesttf) {
|
|
stack[stacksize]= a;
|
|
stacksize++;
|
|
flag[a]= 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
while(stacksize > 0) {
|
|
stacksize--;
|
|
a= stack[stacksize];
|
|
mf= me->mface+a;
|
|
tf= me->tface+a;
|
|
|
|
nverts= mf->v4? 4: 3;
|
|
|
|
for(i=0; i<nverts; i++) {
|
|
vlist= get_uv_map_vert(vmap, *(&mf->v1 + i));
|
|
startv= vlist;
|
|
|
|
for(iterv=vlist; iterv; iterv=iterv->next) {
|
|
if(iterv->separate)
|
|
startv= iterv;
|
|
if(iterv->f == a)
|
|
break;
|
|
}
|
|
|
|
for(iterv=startv; iterv; iterv=iterv->next) {
|
|
if((startv != iterv) && (iterv->separate))
|
|
break;
|
|
else if(!flag[iterv->f]) {
|
|
flag[iterv->f]= 1;
|
|
stack[stacksize]= iterv->f;;
|
|
stacksize++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(mode==0 || mode==2) {
|
|
for(a=0, tf=me->tface; a<me->totface; a++, tf++)
|
|
if(flag[a])
|
|
tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
|
|
else
|
|
tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
|
|
}
|
|
else if(mode==1) {
|
|
mf= me->mface;
|
|
for(a=0, tf=me->tface; a<me->totface; a++, tf++, mf++) {
|
|
if(flag[a]) {
|
|
if (mf->v4) {
|
|
if((tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)))
|
|
break;
|
|
}
|
|
else if(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3))
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (a<me->totface) {
|
|
for(a=0, tf=me->tface; a<me->totface; a++, tf++)
|
|
if(flag[a])
|
|
tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
|
|
}
|
|
else {
|
|
for(a=0, tf=me->tface; a<me->totface; a++, tf++)
|
|
if(flag[a])
|
|
tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
|
|
}
|
|
}
|
|
|
|
MEM_freeN(stack);
|
|
MEM_freeN(flag);
|
|
free_uv_vert_map(vmap);
|
|
|
|
BIF_undo_push("Select linked UV");
|
|
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(tface->flag & TF_SELECT) {
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
BIF_undo_push("Unlink UV selection");
|
|
scrarea_queue_winredraw(curarea);
|
|
}
|
|
|
|
void toggle_uv_select(int mode)
|
|
{
|
|
switch(mode){
|
|
case 'f':
|
|
G.sima->flag ^= SI_SELACTFACE;
|
|
break;
|
|
case 's':
|
|
G.sima->flag ^= SI_STICKYUVS;
|
|
if (G.sima->flag & SI_STICKYUVS) G.sima->flag &= ~SI_LOCALSTICKY;
|
|
else G.sima->flag |= SI_LOCALSTICKY;
|
|
break;
|
|
case 'l':
|
|
G.sima->flag ^= SI_LOCALSTICKY;
|
|
if (G.sima->flag & SI_LOCALSTICKY) G.sima->flag &= ~SI_STICKYUVS;
|
|
break;
|
|
case 'o':
|
|
G.sima->flag &= ~SI_STICKYUVS;
|
|
G.sima->flag &= ~SI_LOCALSTICKY;
|
|
break;
|
|
}
|
|
allqueue(REDRAWIMAGE, 0);
|
|
}
|
|
|
|
void pin_tface_uv(int mode)
|
|
{
|
|
Mesh *me;
|
|
TFace *tface;
|
|
MFace *mface;
|
|
int a;
|
|
|
|
if( is_uv_tface_editing_allowed()==0 ) return;
|
|
me= get_mesh(OBACT);
|
|
|
|
mface= me->mface;
|
|
tface= me->tface;
|
|
for(a=me->totface; a>0; a--, tface++, mface++) {
|
|
if(tface->flag & TF_SELECT) {
|
|
if(mode ==1){
|
|
if(tface->flag & TF_SEL1) tface->unwrap |= TF_PIN1;
|
|
if(tface->flag & TF_SEL2) tface->unwrap |= TF_PIN2;
|
|
if(tface->flag & TF_SEL3) tface->unwrap |= TF_PIN3;
|
|
if(mface->v4)
|
|
if(tface->flag & TF_SEL4) tface->unwrap |= TF_PIN4;
|
|
}
|
|
else if (mode ==0){
|
|
if(tface->flag & TF_SEL1) tface->unwrap &= ~TF_PIN1;
|
|
if(tface->flag & TF_SEL2) tface->unwrap &= ~TF_PIN2;
|
|
if(tface->flag & TF_SEL3) tface->unwrap &= ~TF_PIN3;
|
|
if(mface->v4)
|
|
if(tface->flag & TF_SEL4) tface->unwrap &= ~TF_PIN4;
|
|
}
|
|
}
|
|
}
|
|
|
|
BIF_undo_push("Pin UV");
|
|
scrarea_queue_winredraw(curarea);
|
|
}
|
|
|
|
void select_pinned_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;
|
|
tface= me->tface;
|
|
for(a=me->totface; a>0; a--, tface++, mface++) {
|
|
if(tface->flag & TF_SELECT) {
|
|
|
|
if (tface->unwrap & TF_PIN1) tface->flag |= TF_SEL1;
|
|
if (tface->unwrap & TF_PIN2) tface->flag |= TF_SEL2;
|
|
if (tface->unwrap & TF_PIN3) tface->flag |= TF_SEL3;
|
|
if(mface->v4) {
|
|
if (tface->unwrap & TF_PIN4) tface->flag |= TF_SEL4;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
BIF_undo_push("Select Pinned UVs");
|
|
scrarea_queue_winredraw(curarea);
|
|
}
|
|
|
|
int minmax_tface_uv(float *min, float *max)
|
|
{
|
|
Mesh *me;
|
|
TFace *tf;
|
|
MFace *mf;
|
|
int a, sel;
|
|
|
|
if( is_uv_tface_editing_allowed()==0 ) return 0;
|
|
me= get_mesh(OBACT);
|
|
|
|
INIT_MINMAX2(min, max);
|
|
|
|
sel= 0;
|
|
mf= (MFace*)me->mface;
|
|
tf= (TFace*)me->tface;
|
|
for(a=me->totface; a>0; a--, tf++, mf++) {
|
|
if(tf->flag & TF_HIDE);
|
|
else if(tf->flag & TF_SELECT) {
|
|
|
|
if (tf->flag & TF_SEL1) {
|
|
DO_MINMAX2(tf->uv[0], min, max);
|
|
}
|
|
if (tf->flag & TF_SEL2) {
|
|
DO_MINMAX2(tf->uv[1], min, max);
|
|
}
|
|
if (tf->flag & TF_SEL3) {
|
|
DO_MINMAX2(tf->uv[2], min, max);
|
|
}
|
|
if (mf->v4 && tf->flag & TF_SEL4) {
|
|
DO_MINMAX2(tf->uv[3], min, max);
|
|
}
|
|
|
|
sel = 1;
|
|
}
|
|
}
|
|
|
|
return sel;
|
|
}
|
|
|
|
static void sima_show_info(int x, int y, char *cp, float *fp, int *zp, float *zpf)
|
|
{
|
|
short ofs;
|
|
char str[256];
|
|
|
|
ofs= sprintf(str, "X: %d Y: %d ", x, y);
|
|
if(cp)
|
|
ofs+= sprintf(str+ofs, "| R: %d G: %d B: %d A: %d ", cp[0], cp[1], cp[2], cp[3]);
|
|
if(fp)
|
|
ofs+= sprintf(str+ofs, "| R: %.3f G: %.3f B: %.3f A: %.3f ", fp[0], fp[1], fp[2], fp[3]);
|
|
if(zp)
|
|
ofs+= sprintf(str+ofs, "| Z: %.4f ", 0.5+0.5*( ((float)*zp)/(float)0x7fffffff));
|
|
if(zpf)
|
|
ofs+= sprintf(str+ofs, "| Z: %.3f ", *zpf);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
|
glEnable(GL_BLEND);
|
|
|
|
glColor4f(.0,.0,.0,.25);
|
|
glRectf(0.0, 0.0, curarea->winx, 30.0);
|
|
glDisable(GL_BLEND);
|
|
|
|
glColor3ub(255, 255, 255);
|
|
glRasterPos2i(10, 10);
|
|
|
|
BMF_DrawString(G.fonts, str);
|
|
|
|
}
|
|
|
|
void sima_sample_color(void)
|
|
{
|
|
ImBuf *ibuf;
|
|
float fx, fy;
|
|
short mval[2], mvalo[2], firsttime=1;
|
|
|
|
if(G.sima->image==NULL) return;
|
|
if(G.sima->image->ibuf==NULL) return;
|
|
ibuf= G.sima->image->ibuf;
|
|
|
|
calc_image_view(G.sima, 'f');
|
|
getmouseco_areawin(mvalo);
|
|
|
|
while(get_mbut() & L_MOUSE) {
|
|
|
|
getmouseco_areawin(mval);
|
|
if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1] || firsttime) {
|
|
firsttime= 0;
|
|
areamouseco_to_ipoco(G.v2d, mval, &fx, &fy);
|
|
|
|
if(fx>=0.0 && fy>=0.0 && fx<1.0 && fy<1.0) {
|
|
float *fp= NULL, *zpf= NULL;
|
|
int *zp= NULL;
|
|
char *cp= NULL;
|
|
|
|
int x= (int) (fx*ibuf->x);
|
|
int y= (int) (fy*ibuf->y);
|
|
|
|
if(x>=ibuf->x) x= ibuf->x-1;
|
|
if(y>=ibuf->y) y= ibuf->y-1;
|
|
|
|
if(ibuf->rect)
|
|
cp= (char *)(ibuf->rect + y*ibuf->x + x);
|
|
if(ibuf->zbuf)
|
|
zp= ibuf->zbuf + y*ibuf->x + x;
|
|
if(ibuf->zbuf_float)
|
|
zpf= ibuf->zbuf_float + y*ibuf->x + x;
|
|
if(ibuf->rect_float)
|
|
fp= (ibuf->rect_float + 4*(y*ibuf->x + x));
|
|
|
|
if(G.sima->cumap) {
|
|
float vec[3];
|
|
if(fp==NULL) {
|
|
fp= vec;
|
|
vec[0]= (float)cp[0]/255.0f;
|
|
vec[1]= (float)cp[1]/255.0f;
|
|
vec[2]= (float)cp[2]/255.0f;
|
|
}
|
|
|
|
if(G.qual & LR_CTRLKEY) {
|
|
curvemapping_set_black_white(G.sima->cumap, NULL, fp);
|
|
curvemapping_do_image(G.sima->cumap, G.sima->image);
|
|
}
|
|
else if(G.qual & LR_SHIFTKEY) {
|
|
curvemapping_set_black_white(G.sima->cumap, fp, NULL);
|
|
curvemapping_do_image(G.sima->cumap, G.sima->image);
|
|
}
|
|
}
|
|
|
|
scrarea_do_windraw(curarea);
|
|
myortho2(-0.375, curarea->winx-0.375, -0.375, curarea->winy-0.375);
|
|
glLoadIdentity();
|
|
sima_show_info(x, y, cp, fp, zp, zpf);
|
|
screen_swapbuffers();
|
|
}
|
|
|
|
}
|
|
BIF_wait_for_statechange();
|
|
}
|
|
|
|
scrarea_queue_winredraw(curarea);
|
|
}
|
|
|
|
|