added a transform panel to the UV/Image window - at the moment it sets UV and teh cursor location.

added a stap menu to the UV/Image window for snapping the selection and cursor.
reverted to drawing face dots in editmode when Limit Selection is enabled. even though its not needed for selection its consistent and dosnt look like modes are being changed.
This commit is contained in:
Campbell Barton 2007-09-15 10:43:13 +00:00
parent 427e063777
commit b2a8199d4b
11 changed files with 272 additions and 51 deletions

@ -97,6 +97,7 @@
#define ABS(a) ( (a)<0 ? (-(a)) : (a) )
#define VECCOPY(v1,v2) {*(v1)= *(v2); *(v1+1)= *(v2+1); *(v1+2)= *(v2+2);}
#define VECCOPY2D(v1,v2) {*(v1)= *(v2); *(v1+1)= *(v2+1);}
#define QUATCOPY(v1,v2) {*(v1)= *(v2); *(v1+1)= *(v2+1); *(v1+2)= *(v2+2); *(v1+3)= *(v2+3);}
#define LONGCOPY(a, b, c) {int lcpc=c, *lcpa=(int *)a, *lcpb=(int *)b; while(lcpc-->0) *(lcpa++)= *(lcpb++);}

@ -64,6 +64,7 @@ void imagewin_store_spare(void);
struct ImBuf *imagewindow_get_ibuf(struct SpaceImage *sima);
void image_editvertex_buts(struct uiBlock *block);
void image_editcursor_buts(struct uiBlock *block);
#endif

@ -45,6 +45,7 @@ int is_uv_tface_editing_allowed_silent(void);
void get_connected_limit_tface_uv(float *limit);
int minmax_tface_uv(float *min, float *max);
int cent_tface_uv(float *cent, int mode);
void transform_width_height_tface_uv(int *width, int *height);
void transform_aspect_ratio_tface_uv(float *aspx, float *aspy);
@ -53,6 +54,8 @@ void mouseco_to_cursor_sima(void);
void borderselect_sima(short whichuvs);
void mouseco_to_curtile(void);
void mouse_select_sima(void);
void snap_menu_sima(void);
void select_invert_tface_uv(void);
void select_swap_tface_uv(void);
void mirrormenu_tface_uv(void);

@ -65,6 +65,7 @@ struct SpaceOops;
#define IMAGE_HANDLER_CURVES 32
#define IMAGE_HANDLER_PREVIEW 33
#define IMAGE_HANDLER_GAME_PROPERTIES 34
#define IMAGE_HANDLER_TRANSFORM_PROPERTIES 35
/* action handler codes */
#define ACTION_HANDLER_PROPERTIES 40

@ -332,9 +332,10 @@
#define B_SIMANAME 381
#define B_SIMAMULTI 382
#define B_TRANS_IMAGE 383
#define B_SIMA_REPACK 384
#define B_SIMA_PLAY 385
#define B_SIMA_RECORD 386
#define B_CURSOR_IMAGE 384
#define B_SIMA_REPACK 385
#define B_SIMA_PLAY 386
#define B_SIMA_RECORD 387
/* BUTS: 400 */
#define B_BUTSHOME 401

@ -732,6 +732,26 @@ static void draw_image_view_tool(void)
/* ************ panel stuff ************* */
/* this function gets the values for cursor and vertex number buttons */
static void image_transform_but_attr(int *imx, int *imy, int *step, int *digits) /*, float *xcoord, float *ycoord)*/
{
ImBuf *ibuf= imagewindow_get_ibuf(G.sima);
if(ibuf) {
*imx= ibuf->x;
*imy= ibuf->y;
}
if (G.sima->flag & SI_COORDFLOATS) {
*step= 1;
*digits= 3;
}
else {
*step= 100;
*digits= 2;
}
}
/* is used for both read and write... */
void image_editvertex_buts(uiBlock *block)
{
@ -745,13 +765,7 @@ void image_editvertex_buts(uiBlock *block)
if( is_uv_tface_editing_allowed_silent()==0 ) return;
if (G.sima->image) {
ImBuf *ibuf= imagewindow_get_ibuf(G.sima);
if(ibuf) {
imx= ibuf->x;
imy= ibuf->y;
}
}
image_transform_but_attr(&imx, &imy, &step, &digits);
for (efa= em->faces.first; efa; efa= efa->next) {
if (!(efa->f & SELECT)) continue;
@ -784,24 +798,19 @@ void image_editvertex_buts(uiBlock *block)
ocent[0]= cent[0]/nactive;
ocent[1]= cent[1]/nactive;
if (G.sima->flag & SI_COORDFLOATS) {
step= 1;
digits= 3;
}
else {
} else {
ocent[0] *= imx;
ocent[1] *= imy;
step= 100;
digits= 2;
}
uiBlockBeginAlign(block);
if(nactive==1) {
uiDefButF(block, NUM, B_TRANS_IMAGE, "Vertex X:", 10, 10, 150, 19, &ocent[0], -10*imx, 10.0*imx, step, digits, "");
uiDefButF(block, NUM, B_TRANS_IMAGE, "Vertex Y:", 160, 10, 150, 19, &ocent[1], -10*imy, 10.0*imy, step, digits, "");
uiDefButF(block, NUM, B_TRANS_IMAGE, "Vertex X:", 10, 40, 145, 19, &ocent[0], -10*imx, 10.0*imx, step, digits, "");
uiDefButF(block, NUM, B_TRANS_IMAGE, "Vertex Y:", 10, 20, 145, 19, &ocent[1], -10*imy, 10.0*imy, step, digits, "");
}
else {
uiDefButF(block, NUM, B_TRANS_IMAGE, "Median X:", 10, 10, 150, 19, &ocent[0], -10*imx, 10.0*imx, step, digits, "");
uiDefButF(block, NUM, B_TRANS_IMAGE, "Median Y:", 160, 10, 150, 19, &ocent[1], -10*imy, 10.0*imy, step, digits, "");
uiDefButF(block, NUM, B_TRANS_IMAGE, "Median X:", 10, 40, 145, 19, &ocent[0], -10*imx, 10.0*imx, step, digits, "");
uiDefButF(block, NUM, B_TRANS_IMAGE, "Median Y:", 10, 20, 145, 19, &ocent[1], -10*imy, 10.0*imy, step, digits, "");
}
uiBlockEndAlign(block);
}
@ -821,9 +830,6 @@ void image_editvertex_buts(uiBlock *block)
delta[1]= ocent[1]/imy - cent[1];
}
/*for (i=0; i<me->totface; i++) {
MFace *mf= &((MFace*) me->mface)[i];
MTFace *tf= &((MTFace*) me->mtface)[i];*/
for (efa= em->faces.first; efa; efa= efa->next) {
if (!(efa->f & SELECT)) continue;
tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
@ -851,6 +857,48 @@ void image_editvertex_buts(uiBlock *block)
}
}
/* is used for both read and write... */
void image_editcursor_buts(uiBlock *block)
{
static float ocent[2];
/*float cent[2]= {0.0, 0.0};*/
int imx= 256, imy= 256;
int step, digits;
if( is_uv_tface_editing_allowed_silent()==0 ) return;
image_transform_but_attr(&imx, &imy, &step, &digits);
if(block) { // do the buttons
ocent[0]= G.v2d->cursor[0];
ocent[1]= G.v2d->cursor[1];
if (G.sima->flag & SI_COORDFLOATS) {
} else {
ocent[0] *= imx;
ocent[1] *= imy;
}
uiBlockBeginAlign(block);
uiDefButF(block, NUM, B_CURSOR_IMAGE, "Cursor X:", 165, 40, 145, 19, &ocent[0], -10*imx, 10.0*imx, step, digits, "");
uiDefButF(block, NUM, B_CURSOR_IMAGE, "Cursor Y:", 165, 20, 145, 19, &ocent[1], -10*imy, 10.0*imy, step, digits, "");
uiBlockEndAlign(block);
}
else { // apply event
if (G.sima->flag & SI_COORDFLOATS) {
G.v2d->cursor[0]= ocent[0];
G.v2d->cursor[1]= ocent[1];
}
else {
G.v2d->cursor[0]= ocent[0]/imx;
G.v2d->cursor[1]= ocent[1]/imy;
}
allqueue(REDRAWIMAGE, 0);
}
}
void image_info(Image *ima, ImBuf *ibuf, char *str)
{
int ofs= 0;
@ -900,13 +948,11 @@ static void image_panel_properties(short cntrl) // IMAGE_HANDLER_PROPERTIES
block= uiNewBlock(&curarea->uiblocks, "image_panel_properties", UI_EMBOSS, UI_HELV, curarea->win);
uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl);
uiSetPanelHandler(IMAGE_HANDLER_PROPERTIES); // for close and esc
if(uiNewPanel(curarea, block, "Properties", "Image", 10, 10, 318, 204)==0)
if(uiNewPanel(curarea, block, "Image Properties", "Image", 10, 10, 318, 204)==0)
return;
/* note, it draws no bottom half in facemode, for vertex buttons */
uiblock_image_panel(block, &G.sima->image, &G.sima->iuser, B_REDR, B_REDR);
image_editvertex_buts(block);
}
static void image_panel_game_properties(short cntrl) // IMAGE_HANDLER_GAME_PROPERTIES
@ -946,6 +992,22 @@ static void image_panel_game_properties(short cntrl) // IMAGE_HANDLER_GAME_PROPE
}
}
static void image_panel_transform_properties(short cntrl) // IMAGE_HANDLER_TRANSFORM_PROPERTIES
{
uiBlock *block;
block= uiNewBlock(&curarea->uiblocks, "image_transform_properties", UI_EMBOSS, UI_HELV, curarea->win);
uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl);
uiSetPanelHandler(IMAGE_HANDLER_TRANSFORM_PROPERTIES); // for close and esc
if(uiNewPanel(curarea, block, "Transform Properties", "Image", 10, 10, 318, 204)==0)
return;
uiDefButBitI(block, TOG, SI_COORDFLOATS, B_SIMAGEDRAW1, "Normalized Coords", 10,80,140,19, &G.sima->flag, 0, 0, 0, 0, "Display coords from 0.0 to 1.0 rather then in pixels");
image_editvertex_buts(block);
image_editcursor_buts(block);
}
static void image_panel_paint(short cntrl) // IMAGE_HANDLER_PAINT
{
/* B_SIMABRUSHCHANGE only redraws and eats the mouse messages */
@ -1259,6 +1321,10 @@ static void image_blockhandlers(ScrArea *sa)
case IMAGE_HANDLER_GAME_PROPERTIES:
image_panel_game_properties(sima->blockhandler[a+1]);
break;
case IMAGE_HANDLER_TRANSFORM_PROPERTIES:
if (EM_texFaceCheck())
image_panel_transform_properties(sima->blockhandler[a+1]);
break;
case IMAGE_HANDLER_PAINT:
image_panel_paint(sima->blockhandler[a+1]);
break;

@ -1633,8 +1633,7 @@ static void draw_em_fancy_verts(EditMesh *em, DerivedMesh *cageDM)
}
if( (G.scene->selectmode & SCE_SELECT_FACE) &&
(G.vd->drawtype<=OB_SOLID) &&
( !((G.vd->flag & V3D_ZBUF_SELECT) && (G.vd->drawtype==OB_SOLID)) )
(G.vd->drawtype<=OB_SOLID)
) {
glPointSize(fsize);
glColor4ubv((GLubyte *)fcol);
@ -4453,8 +4452,7 @@ static int bbs_mesh_solid_EM(DerivedMesh *dm, int facecol)
dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, (void*)(long) 1, 0);
if( (G.scene->selectmode & SCE_SELECT_FACE) &&
(G.vd->drawtype<=OB_SOLID) &&
( !((G.vd->flag & V3D_ZBUF_SELECT) && (G.vd->drawtype==OB_SOLID)) )
(G.vd->drawtype<=OB_SOLID)
) {
glPointSize(BIF_GetThemeValuef(TH_FACEDOT_SIZE));

@ -265,16 +265,11 @@ void weld_align_tface_uv(char tool)
EditMesh *em = G.editMesh;
EditFace *efa;
MTFace *tface;
float min[2], max[2], cent[2];
float cent[2];
int a;
if( is_uv_tface_editing_allowed()==0 ) return;
if (!minmax_tface_uv(min, max))
return;
cent[0]= (min[0]+max[0])/2.0;
cent[1]= (min[1]+max[1])/2.0;
cent_tface_uv(cent, 0);
if(tool == 'x' || tool == 'w') {
for (a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
@ -765,6 +760,108 @@ void borderselect_sima(short whichuvs)
}
}
int snap_uv_sel_to_curs(void)
{
EditMesh *em = G.editMesh;
EditFace *efa;
MTFace *tface;
short change = 0;
for (efa= em->faces.first; efa; efa= efa->next) {
if(efa->f & SELECT) {
tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
if (tface->flag & TF_SEL1) VECCOPY2D(tface->uv[0], G.v2d->cursor);
if (tface->flag & TF_SEL2) VECCOPY2D(tface->uv[1], G.v2d->cursor);
if (tface->flag & TF_SEL3) VECCOPY2D(tface->uv[2], G.v2d->cursor);
if (efa->v4)
if (tface->flag & TF_SEL4) VECCOPY2D(tface->uv[3], G.v2d->cursor);
change = 1;
}
}
return change;
}
void snap_coord_to_pixel(float *uvco, float w, float h)
{
uvco[0] = ((float) ((int)((uvco[0]*w) + 0.5))) / w;
uvco[1] = ((float) ((int)((uvco[1]*h) + 0.5))) / h;
}
int snap_uv_sel_to_pixels(void) /* warning, sanity checks must alredy be done */
{
EditMesh *em = G.editMesh;
EditFace *efa;
MTFace *tface;
int wi, hi;
float w, h;
short change = 0;
transform_width_height_tface_uv(&wi, &hi);
w = (float)wi;
h = (float)hi;
for (efa= em->faces.first; efa; efa= efa->next) {
if(efa->f & SELECT) {
tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
if (tface->flag & TF_SEL1) snap_coord_to_pixel(tface->uv[0], w, h);
if (tface->flag & TF_SEL2) snap_coord_to_pixel(tface->uv[1], w, h);
if (tface->flag & TF_SEL3) snap_coord_to_pixel(tface->uv[2], w, h);
if (efa->v4)
if (tface->flag & TF_SEL4) snap_coord_to_pixel(tface->uv[3], w, h);
change = 1;
}
}
return change;
}
void snap_uv_curs_to_pixels(void)
{
int wi, hi;
float w, h;
transform_width_height_tface_uv(&wi, &hi);
w = (float)wi;
h = (float)hi;
snap_coord_to_pixel(G.v2d->cursor, w, h);
}
int snap_uv_curs_to_sel(void)
{
if( is_uv_tface_editing_allowed()==0 ) return 0;
return cent_tface_uv(G.v2d->cursor, 0);
}
void snap_menu_sima(void)
{
short event;
if( is_uv_tface_editing_allowed()==0 || !G.v2d) return; /* !G.v2d should never happen */
event = pupmenu("Snap %t|Selection -> Pixels%x1|Selection -> Cursor%x2|Cursor-> Pixel%x3|Cursor-> Selection%x4");
switch (event) {
case 1:
if (snap_uv_sel_to_pixels()) {
BIF_undo_push("Snap UV Selection to Pixels");
object_uvs_changed(OBACT);
}
break;
case 2:
if (snap_uv_sel_to_curs()) {
BIF_undo_push("Snap UV Selection to Cursor");
object_uvs_changed(OBACT);
}
break;
case 3:
snap_uv_curs_to_pixels();
scrarea_queue_winredraw(curarea);
break;
case 4:
if (snap_uv_curs_to_sel())
allqueue(REDRAWIMAGE, 0);
break;
}
}
/** 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
@ -1299,10 +1396,46 @@ int minmax_tface_uv(float *min, float *max)
sel = 1;
}
}
return sel;
}
int cent_tface_uv(float *cent, int mode)
{
float min[2], max[2];
short change= 0;
switch (mode) {
case 0:
if (minmax_tface_uv(min, max))
change = 1;
break;
case 1:
{
EditFace *efa;
MTFace *tf;
INIT_MINMAX2(min, max);
for (efa= G.editMesh->faces.first; efa; efa= efa->next) {
if(efa->f & SELECT && efa->h==0) {
tf = CustomData_em_get(&G.editMesh->fdata, efa->data, CD_MTFACE);
if (tf->flag & TF_SEL1) { DO_MINMAX2(tf->uv[0], min, max); change= 1;}
if (tf->flag & TF_SEL2) { DO_MINMAX2(tf->uv[1], min, max); change= 1;}
if (tf->flag & TF_SEL3) { DO_MINMAX2(tf->uv[2], min, max); change= 1;}
if (efa->v4 && tf->flag & TF_SEL4) { DO_MINMAX2(tf->uv[3], min, max); change= 1;}
}
}
break;
}
}
if (change) {
cent[0]= (min[0]+max[0])/2.0;
cent[1]= (min[1]+max[1])/2.0;
return 1;
}
return 0;
}
static void sima_show_info(int channels, int x, int y, char *cp, float *fp, int *zp, float *zpf)
{
short ofs;

@ -225,6 +225,9 @@ void do_image_buttons(unsigned short event)
case B_TRANS_IMAGE:
image_editvertex_buts(NULL);
break;
case B_CURSOR_IMAGE:
image_editcursor_buts(NULL);
break;
case B_TWINANIM:
{
@ -455,7 +458,6 @@ static void do_image_viewmenu(void *arg, int event)
case 13: /* Realtime Panel... */
add_blockhandler(curarea, IMAGE_HANDLER_GAME_PROPERTIES, UI_PNL_UNSTOW);
break;
}
allqueue(REDRAWVIEW3D, 0);
}
@ -469,7 +471,7 @@ static uiBlock *image_viewmenu(void *arg_unused)
block= uiNewBlock(&curarea->uiblocks, "image_viewmenu", UI_EMBOSSP, UI_HELV, curarea->headwin);
uiBlockSetButmFunc(block, do_image_viewmenu, NULL);
uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Properties...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, "");
uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Image Properties...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, "");
uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Real-time Properties...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 13, "");
uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Paint Tool...|C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, "");
uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Curves Tool...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 11, "");
@ -968,6 +970,9 @@ static void do_image_uvsmenu(void *arg, int event)
{
switch(event) {
case 0: /* UV Transform Properties Panel... */
add_blockhandler(curarea, IMAGE_HANDLER_TRANSFORM_PROPERTIES, UI_PNL_UNSTOW);
break;
case 1: /* UVs Constrained Rectangular */
if(G.sima->flag & SI_BE_SQUARE) G.sima->flag &= ~SI_BE_SQUARE;
else G.sima->flag |= SI_BE_SQUARE;
@ -1020,9 +1025,9 @@ static uiBlock *image_uvsmenu(void *arg_unused)
block= uiNewBlock(&curarea->uiblocks, "image_uvsmenu", UI_EMBOSSP, UI_HELV, curarea->headwin);
uiBlockSetButmFunc(block, do_image_uvsmenu, NULL);
// uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Transform Properties...|N", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
// uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Transform Properties...|N", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
if(G.sima->flag & SI_PIXELSNAP) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Snap to Pixels|", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, "");
else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap to Pixels|", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, "");
@ -1171,7 +1176,7 @@ void image_buttons(void)
xco= std_libbuttons(block, xco, 0, 0, NULL, B_SIMABROWSE, ID_IM, 0, (ID *)ima, 0, &(G.sima->imanr), 0, 0, B_IMAGEDELETE, 0, 0);
/* UV EditMode buttons */
if (EM_texFaceCheck()) {
if (EM_texFaceCheck() && (G.sima->flag & SI_DRAWTOOL)==0) {
xco+=10;
uiDefIconTextButS(block, ICONTEXTROW,B_AROUND, ICON_ROTATE, around_pup(), xco,0,XIC+10,YIC, &(G.v2d->around), 0, 3.0, 0, 0, "Rotation/Scaling Pivot (Hotkeys: Comma, Shift Comma, Period) ");
xco+= XIC+15;

@ -4532,7 +4532,10 @@ static char *around_pup(void)
str += sprintf(str, "%s", "|Median Point %x3");
str += sprintf(str, "%s", "|3D Cursor %x1");
str += sprintf(str, "%s", "|Individual Centers %x2");
str += sprintf(str, "%s", "|Active Object %x4");
if ((G.obedit) && (G.obedit->type == OB_MESH))
str += sprintf(str, "%s", "|Active Vert/Edge/Face %x4");
else
str += sprintf(str, "%s", "|Active Object %x4");
return string;
}

@ -4762,7 +4762,7 @@ static void winqreadimagespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
} else if (event == RIGHTMOUSE) {
event = LEFTMOUSE;
}
}
}
if (sima->image && (sima->flag & SI_DRAWTOOL)) {
switch(event) {
@ -4891,13 +4891,18 @@ static void winqreadimagespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
}
break;
case SKEY:
if((G.qual==0) && is_uv_tface_editing_allowed()) {
initTransform(TFM_RESIZE, CTX_NONE);
Transform();
if (is_uv_tface_editing_allowed()) {
if ( G.qual==LR_SHIFTKEY) {
/* Snap */
snap_menu_sima();
} else if (G.qual==0) {
initTransform(TFM_RESIZE, CTX_NONE);
Transform();
}
}
break;
case VKEY:
if((G.qual==0))
if(G.qual==LR_SHIFTKEY)
stitch_uv_tface(0);
else if(G.qual==LR_SHIFTKEY)
stitch_uv_tface(1);
@ -4968,7 +4973,11 @@ static void winqreadimagespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
new_image_sima();
}
else if(G.qual==0) {
toggle_blockhandler(sa, IMAGE_HANDLER_PROPERTIES, UI_PNL_TO_MOUSE);
if (EM_texFaceCheck()) {
toggle_blockhandler(sa, IMAGE_HANDLER_TRANSFORM_PROPERTIES, UI_PNL_TO_MOUSE);
} else {
toggle_blockhandler(sa, IMAGE_HANDLER_PROPERTIES, UI_PNL_TO_MOUSE);
}
scrarea_queue_winredraw(sa);
}
break;