diff options
Diffstat (limited to 'source/blender/editors/uvedit/uvedit_ops.c')
-rw-r--r-- | source/blender/editors/uvedit/uvedit_ops.c | 1043 |
1 files changed, 578 insertions, 465 deletions
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 71e64886e34..86f5c782ca3 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -54,8 +54,6 @@ #include "BKE_report.h" #include "BKE_utildefines.h" -#include "IMB_imbuf_types.h" // XXX remove? - #include "BIF_transform.h" #include "ED_mesh.h" @@ -71,15 +69,11 @@ #include "UI_view2d.h" #include "uvedit_intern.h" - -/* local prototypes */ -static void sel_uvco_inside_radius(SpaceImage *sima, Scene *scene, short sel, EditFace *efa, MTFace *tface, int index, float *offset, float *ell, short select_index); -void uvedit_selectionCB(SpaceImage *sima, Scene *scene, ARegion *ar, short selecting, Object *obedit, short *mval, float rad); /* used in edit.c */ -void uvface_setsel__internal(bContext *C, SpaceImage *sima, Scene *scene, Object *obedit, short select); +#include "../space_image/image_intern.h" /************************* state testing ************************/ -int ED_uvedit_test_silent(Object *obedit) +int ED_uvedit_test(Object *obedit) { if(obedit->type != OB_MESH) return 0; @@ -87,14 +81,6 @@ int ED_uvedit_test_silent(Object *obedit) return EM_texFaceCheck(((Mesh*)obedit->data)->edit_mesh); } -int ED_uvedit_test(Object *obedit) -{ - // XXX if(!obedit) - // XXX error("Enter Edit Mode to perform this action"); - - return ED_uvedit_test_silent(obedit); -} - /************************* assign image ************************/ void ED_uvedit_assign_image(Scene *scene, Object *obedit, Image *ima, Image *previma) @@ -162,7 +148,7 @@ void ED_uvedit_set_tile(Scene *scene, Object *obedit, Image *ima, int curtile, i MTFace *tf; /* verify if we have something to do */ - if(!ima || !ED_uvedit_test_silent(obedit)) + if(!ima || !ED_uvedit_test(obedit)) return; /* skip assigning these procedural images... */ @@ -193,19 +179,11 @@ void ED_uvedit_set_tile(Scene *scene, Object *obedit, Image *ima, int curtile, i /*********************** space conversion *********************/ -static void uvedit_pixel_to_float(bContext *C, float *dist, float pixeldist) +static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist) { - ImBuf *ibuf= CTX_data_edit_image_buffer(C); - float width, height; + int width, height; - if(ibuf && ibuf->x > 0 && ibuf->y > 0) { - width= ibuf->x; - height= ibuf->y; - } - else { - width= 256.0f; - height= 256.0f; - } + get_space_image_size(sima, &width, &height); dist[0]= pixeldist/width; dist[1]= pixeldist/height; @@ -946,12 +924,6 @@ static void select_linked(Scene *scene, Image *ima, EditMesh *em, float limit[2] /* ******************** mirror operator **************** */ -/* XXX */ -#if 0 - short mode= 0; - mode= pupmenu("Mirror%t|X Axis%x1|Y Axis%x2|"); -#endif - static int mirror_exec(bContext *C, wmOperator *op) { float mat[3][3]; @@ -984,7 +956,7 @@ void UV_OT_mirror(wmOperatorType *ot) /* identifiers */ ot->name= "Mirror"; ot->idname= "UV_OT_mirror"; - ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/; + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; /* api callbacks */ ot->exec= mirror_exec; @@ -996,22 +968,6 @@ void UV_OT_mirror(wmOperatorType *ot) /* ******************** align operator **************** */ -/* XXX */ -#if 0 -void weld_align_menu_tface_uv(bContext *C) -{ - short mode= 0; - - mode= pupmenu("Weld/Align%t|Weld%x1|Align Auto%x2|Align X%x3|Align Y%x4"); - - if(mode==-1) return; - if(mode==1) weld_align_uv(C, 'w'); - else if(mode==2) weld_align_uv(C, 'a'); - else if(mode==3) weld_align_uv(C, 'x'); - else if(mode==4) weld_align_uv(C, 'y'); -} -#endif - static void weld_align_uv(bContext *C, int tool) { Scene *scene; @@ -1083,7 +1039,7 @@ static void weld_align_uv(bContext *C, int tool) } DAG_object_flush_update(scene, obedit, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); // XXX + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit); } static int align_exec(bContext *C, wmOperator *op) @@ -1104,7 +1060,7 @@ void UV_OT_align(wmOperatorType *ot) /* identifiers */ ot->name= "Align"; ot->idname= "UV_OT_align"; - ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/; + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; /* api callbacks */ ot->exec= align_exec; @@ -1128,7 +1084,7 @@ void UV_OT_weld(wmOperatorType *ot) /* identifiers */ ot->name= "Weld"; ot->idname= "UV_OT_weld"; - ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/; + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; /* api callbacks */ ot->exec= weld_exec; @@ -1145,6 +1101,7 @@ typedef struct UVVertAverage { static int stitch_exec(bContext *C, wmOperator *op) { + SpaceImage *sima; Scene *scene; Object *obedit; EditMesh *em; @@ -1153,6 +1110,7 @@ static int stitch_exec(bContext *C, wmOperator *op) Image *ima; MTFace *tf; + sima= (SpaceImage*)CTX_wm_space_data(C); scene= CTX_data_scene(C); obedit= CTX_data_edit_object(C); em= ((Mesh*)obedit->data)->edit_mesh; @@ -1165,7 +1123,7 @@ static int stitch_exec(bContext *C, wmOperator *op) int a, vtot; pixels= RNA_float_get(op->ptr, "limit"); - uvedit_pixel_to_float(C, limit, pixels); + uvedit_pixel_to_float(sima, limit, pixels); EM_init_index_arrays(em, 0, 0, 1); vmap= EM_make_uv_vert_map(em, 1, 0, limit); @@ -1298,7 +1256,7 @@ static int stitch_exec(bContext *C, wmOperator *op) } DAG_object_flush_update(scene, obedit, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); // XXX + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit); return OPERATOR_FINISHED; } @@ -1308,7 +1266,7 @@ void UV_OT_stitch(wmOperatorType *ot) /* identifiers */ ot->name= "Stitch"; ot->idname= "UV_OT_stitch"; - ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/; + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; /* api callbacks */ ot->exec= stitch_exec; @@ -1336,7 +1294,7 @@ static int select_inverse_exec(bContext *C, wmOperator *op) ima= CTX_data_edit_image(C); if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) { - // XXX selectswap_mesh(); + EM_select_swap(em); } else { for(efa= em->faces.first; efa; efa= efa->next) { @@ -1361,7 +1319,7 @@ void UV_OT_select_invert(wmOperatorType *ot) /* identifiers */ ot->name= "Select Invert"; ot->idname= "UV_OT_select_invert"; - ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/; + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; /* api callbacks */ ot->exec= select_inverse_exec; @@ -1386,7 +1344,7 @@ static int de_select_all_exec(bContext *C, wmOperator *op) ima= CTX_data_edit_image(C); if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) { - // XXX deselectall_mesh(); + EM_toggle_select_all(em); } else { sel= 0; @@ -1426,9 +1384,9 @@ static int de_select_all_exec(bContext *C, wmOperator *op) void UV_OT_de_select_all(wmOperatorType *ot) { /* identifiers */ - ot->name= "Select/Deselect All"; + ot->name= "Select or Deselect All"; ot->idname= "UV_OT_de_select_all"; - ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/; + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; /* api callbacks */ ot->exec= de_select_all_exec; @@ -1474,8 +1432,8 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop) int flush = 0; /* 0 == dont flush, 1 == sel, -1 == desel; only use when selection sync is enabled */ float limit[2], *hituv[4], penalty[2]; - uvedit_pixel_to_float(C, limit, 0.05f); - uvedit_pixel_to_float(C, penalty, 5.0f); + uvedit_pixel_to_float(sima, limit, 0.05f); + uvedit_pixel_to_float(sima, penalty, 5.0f); /* retrieve operation mode */ if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) { @@ -1494,9 +1452,6 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop) sync= 0; selectmode= scene->toolsettings->uv_selectmode; sticky= sima->sticky; - - /* XXX if(sticky == SI_STICKY_VERTEX && (G.qual & LR_CTRLKEY)) - sticky= SI_STICKY_DISABLE;*/ } /* find nearest element */ @@ -1711,10 +1666,6 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop) } } - // XXX force_draw(1); - // XXX BIF_undo_push("Select UV"); - // XXX rightmouse_transform(); - DAG_object_flush_update(scene, obedit, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); @@ -1753,7 +1704,7 @@ void UV_OT_select(wmOperatorType *ot) /* identifiers */ ot->name= "Select"; ot->idname= "UV_OT_select"; - ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/; + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; /* api callbacks */ ot->exec= select_exec; @@ -1801,7 +1752,7 @@ void UV_OT_loop_select(wmOperatorType *ot) /* identifiers */ ot->name= "Loop Select"; ot->idname= "UV_OT_loop_select"; - ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/; + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; /* api callbacks */ ot->exec= loop_select_exec; @@ -1819,6 +1770,7 @@ void UV_OT_loop_select(wmOperatorType *ot) static int select_linked_exec(bContext *C, wmOperator *op) { + SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C); Scene *scene= CTX_data_scene(C); Object *obedit= CTX_data_edit_object(C); Image *ima= CTX_data_edit_image(C); @@ -1832,7 +1784,7 @@ static int select_linked_exec(bContext *C, wmOperator *op) } extend= RNA_boolean_get(op->ptr, "extend"); - uvedit_pixel_to_float(C, limit, 0.05f); + uvedit_pixel_to_float(sima, limit, 0.05f); select_linked(scene, ima, em, limit, NULL, extend); DAG_object_flush_update(scene, obedit, OB_RECALC_DATA); @@ -1846,7 +1798,7 @@ void UV_OT_select_linked(wmOperatorType *ot) /* identifiers */ ot->name= "Select Linked"; ot->idname= "UV_OT_select_linked"; - ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/; + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; /* api callbacks */ ot->exec= select_linked_exec; @@ -1899,7 +1851,7 @@ void UV_OT_unlink_selection(wmOperatorType *ot) /* identifiers */ ot->name= "Unlink Selection"; ot->idname= "UV_OT_unlink_selection"; - ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/; + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; /* api callbacks */ ot->exec= unlink_selection_exec; @@ -1908,118 +1860,453 @@ void UV_OT_unlink_selection(wmOperatorType *ot) /* ******************** border select operator **************** */ -void borderselect_sima(bContext *C, SpaceImage *sima, Scene *scene, Image *ima, Object *obedit, short whichuvs) +/* This function sets the selection on tagged faces, need because settings the + * selection a face is done in a number of places but it also needs to respect + * the sticky modes for the UV verts, so dealing with the sticky modes is best + * done in a seperate function. + * + * De-selects faces that have been tagged on efa->tmp.l. */ + +static void uv_faces_do_sticky(bContext *C, SpaceImage *sima, Scene *scene, Object *obedit, short select) +{ + /* Selecting UV Faces with some modes requires us to change + * the selection in other faces (depending on the sticky mode). + * + * This only needs to be done when the Mesh is not used for + * selection (so for sticky modes, vertex or location based). */ + + EditMesh *em= ((Mesh*)obedit->data)->edit_mesh; + EditFace *efa; + MTFace *tf; + int nverts, i; + + if((scene->toolsettings->uv_flag & UV_SYNC_SELECTION)==0 && sima->sticky == SI_STICKY_VERTEX) { + /* Tag all verts as untouched, then touch the ones that have a face center + * in the loop and select all MTFace UV's that use a touched vert. */ + EditVert *eve; + + for(eve= em->verts.first; eve; eve= eve->next) + eve->tmp.l = 0; + + for(efa= em->faces.first; efa; efa= efa->next) { + if(efa->tmp.l) { + if(efa->v4) + efa->v1->tmp.l= efa->v2->tmp.l= efa->v3->tmp.l= efa->v4->tmp.l=1; + else + efa->v1->tmp.l= efa->v2->tmp.l= efa->v3->tmp.l= 1; + } + } + + /* now select tagged verts */ + for(efa= em->faces.first; efa; efa= efa->next) { + tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + nverts= efa->v4? 4: 3; + for(i=0; i<nverts; i++) { + if((*(&efa->v1 + i))->tmp.l) { + if(select) + uvedit_uv_select(scene, efa, tf, i); + else + uvedit_uv_deselect(scene, efa, tf, i); + } + } + } + } + else if((scene->toolsettings->uv_flag & UV_SYNC_SELECTION)==0 && sima->sticky == SI_STICKY_LOC) { + EditFace *efa_vlist; + MTFace *tf_vlist; + UvMapVert *start_vlist=NULL, *vlist_iter; + struct UvVertMap *vmap; + float limit[2]; + int efa_index; + //EditVert *eve; /* removed vert counting for now */ + //int a; + + uvedit_pixel_to_float(sima, limit, 0.05); + + EM_init_index_arrays(em, 0, 0, 1); + vmap= EM_make_uv_vert_map(em, 0, 0, limit); + + /* verts are numbered above in make_uv_vert_map_EM, make sure this stays true! */ + /*for(a=0, eve= em->verts.first; eve; a++, eve= eve->next) + eve->tmp.l = a; */ + + if(vmap == NULL) + return; + + for(efa_index=0, efa= em->faces.first; efa; efa_index++, efa= efa->next) { + if(efa->tmp.l) { + tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + nverts= efa->v4? 4: 3; + + for(i=0; i<nverts; i++) { + if(select) + uvedit_uv_select(scene, efa, tf, i); + else + uvedit_uv_deselect(scene, efa, tf, i); + + vlist_iter= EM_get_uv_map_vert(vmap, (*(&efa->v1 + i))->tmp.l); + + while (vlist_iter) { + if(vlist_iter->separate) + start_vlist = vlist_iter; + + if(efa_index == vlist_iter->f) + break; + + vlist_iter = vlist_iter->next; + } + + vlist_iter = start_vlist; + while (vlist_iter) { + + if(vlist_iter != start_vlist && vlist_iter->separate) + break; + + if(efa_index != vlist_iter->f) { + efa_vlist = EM_get_face_for_index(vlist_iter->f); + tf_vlist = CustomData_em_get(&em->fdata, efa_vlist->data, CD_MTFACE); + + if(select) + uvedit_uv_select(scene, efa_vlist, tf_vlist, vlist_iter->tfindex); + else + uvedit_uv_deselect(scene, efa_vlist, tf_vlist, vlist_iter->tfindex); + } + vlist_iter = vlist_iter->next; + } + } + } + } + EM_free_index_arrays(); + EM_free_uv_vert_map(vmap); + + } + else { /* SI_STICKY_DISABLE or scene->toolsettings->uv_flag & UV_SYNC_SELECTION */ + for(efa= em->faces.first; efa; efa= efa->next) { + if(efa->tmp.l) { + tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + if(select) + uvedit_face_select(scene, efa, tf); + else + uvedit_face_deselect(scene, efa, tf); + } + } + } +} + +static int border_select_exec(bContext *C, wmOperator *op) { + SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C); + Scene *scene= CTX_data_scene(C); + Object *obedit= CTX_data_edit_object(C); + Image *ima= CTX_data_edit_image(C); + ARegion *ar= CTX_wm_region(C); EditMesh *em= ((Mesh*)obedit->data)->edit_mesh; EditFace *efa; MTFace *tface; rcti rect; rctf rectf; - int val, ok = 1; - short mval[2], select; + int change, pinned, select, faces; - if(!ED_uvedit_test(obedit)) return; + /* get rectangle from operator */ + rect.xmin= RNA_int_get(op->ptr, "xmin"); + rect.ymin= RNA_int_get(op->ptr, "ymin"); + rect.xmax= RNA_int_get(op->ptr, "xmax"); + rect.ymax= RNA_int_get(op->ptr, "ymax"); + + UI_view2d_region_to_view(&ar->v2d, rect.xmin, rect.ymin, &rectf.xmin, &rectf.ymin); + UI_view2d_region_to_view(&ar->v2d, rect.xmax, rect.ymax, &rectf.xmax, &rectf.ymax); - val= 0; // XXX get_border(&rect, 3); - select = 0; // XXX (val==LEFTMOUSE) ? 1 : 0; + /* figure out what to select/deselect */ + select= (RNA_int_get(op->ptr, "event_type") == LEFTMOUSE); // XXX hardcoded + pinned= RNA_boolean_get(op->ptr, "pinned"); - if(val) { - mval[0]= rect.xmin; - mval[1]= rect.ymin; - // XXX areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin); - mval[0]= rect.xmax; - mval[1]= rect.ymax; - // XXX areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax); - - if(0) { // XXX draw_uvs_face_check() && whichuvs != UV_SELECT_PINNED) { - float cent[2]; - ok = 0; - for(efa= em->faces.first; efa; efa= efa->next) { - /* assume not touched */ - efa->tmp.l = 0; - tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - if(uvedit_face_visible(scene, ima, efa, tface)) { - uv_center(tface->uv, cent, efa->v4 != NULL); - if(BLI_in_rctf(&rectf, cent[0], cent[1])) { - efa->tmp.l = ok = 1; - } + if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) + faces= (scene->selectmode == SCE_SELECT_FACE); + else + faces= (scene->toolsettings->uv_selectmode == UV_SELECT_FACE); + + /* do actual selection */ + if(faces && !pinned) { + /* handle face selection mode */ + float cent[2]; + + change= 0; + + for(efa= em->faces.first; efa; efa= efa->next) { + /* assume not touched */ + efa->tmp.l = 0; + tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + if(uvedit_face_visible(scene, ima, efa, tface)) { + uv_center(tface->uv, cent, efa->v4 != NULL); + if(BLI_in_rctf(&rectf, cent[0], cent[1])) { + efa->tmp.l = change = 1; } } - /* (de)selects all tagged faces and deals with sticky modes */ - if(ok) - uvface_setsel__internal(C, sima, scene, obedit, select); } - else { - for(efa= em->faces.first; efa; efa= efa->next) { - tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - if(uvedit_face_visible(scene, ima, efa, tface)) { - if(whichuvs == UV_SELECT_ALL || (scene->toolsettings->uv_flag & UV_SYNC_SELECTION) ) { - /* UV_SYNC_SELECTION - cant do pinned selection */ - if(BLI_in_rctf(&rectf, tface->uv[0][0], tface->uv[0][1])) { - if(select) uvedit_uv_select(scene, efa, tface, 0); - else uvedit_uv_deselect(scene, efa, tface, 0); - } - if(BLI_in_rctf(&rectf, tface->uv[1][0], tface->uv[1][1])) { - if(select) uvedit_uv_select(scene, efa, tface, 1); - else uvedit_uv_deselect(scene, efa, tface, 1); - } - if(BLI_in_rctf(&rectf, tface->uv[2][0], tface->uv[2][1])) { - if(select) uvedit_uv_select(scene, efa, tface, 2); - else uvedit_uv_deselect(scene, efa, tface, 2); - } - if(efa->v4 && BLI_in_rctf(&rectf, tface->uv[3][0], tface->uv[3][1])) { - if(select) uvedit_uv_select(scene, efa, tface, 3); - else uvedit_uv_deselect(scene, efa, tface, 3); - } - } else if(whichuvs == UV_SELECT_PINNED) { - if((tface->unwrap & TF_PIN1) && - BLI_in_rctf(&rectf, tface->uv[0][0], tface->uv[0][1])) { - - if(select) uvedit_uv_select(scene, efa, tface, 0); - else uvedit_uv_deselect(scene, efa, tface, 0); - } - if((tface->unwrap & TF_PIN2) && - BLI_in_rctf(&rectf, tface->uv[1][0], tface->uv[1][1])) { - - if(select) uvedit_uv_select(scene, efa, tface, 1); - else uvedit_uv_deselect(scene, efa, tface, 1); - } - if((tface->unwrap & TF_PIN3) && - BLI_in_rctf(&rectf, tface->uv[2][0], tface->uv[2][1])) { - - if(select) uvedit_uv_select(scene, efa, tface, 2); - else uvedit_uv_deselect(scene, efa, tface, 2); - } - if((efa->v4) && (tface->unwrap & TF_PIN4) && BLI_in_rctf(&rectf, tface->uv[3][0], tface->uv[3][1])) { - if(select) uvedit_uv_select(scene, efa, tface, 3); - else uvedit_uv_deselect(scene, efa, tface, 3); - } + + /* (de)selects all tagged faces and deals with sticky modes */ + if(change) + uv_faces_do_sticky(C, sima, scene, obedit, select); + } + else { + /* other selection modes */ + change= 1; + + for(efa= em->faces.first; efa; efa= efa->next) { + tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + if(uvedit_face_visible(scene, ima, efa, tface)) { + if(!pinned || (scene->toolsettings->uv_flag & UV_SYNC_SELECTION) ) { + /* UV_SYNC_SELECTION - can't do pinned selection */ + if(BLI_in_rctf(&rectf, tface->uv[0][0], tface->uv[0][1])) { + if(select) uvedit_uv_select(scene, efa, tface, 0); + else uvedit_uv_deselect(scene, efa, tface, 0); + } + if(BLI_in_rctf(&rectf, tface->uv[1][0], tface->uv[1][1])) { + if(select) uvedit_uv_select(scene, efa, tface, 1); + else uvedit_uv_deselect(scene, efa, tface, 1); + } + if(BLI_in_rctf(&rectf, tface->uv[2][0], tface->uv[2][1])) { + if(select) uvedit_uv_select(scene, efa, tface, 2); + else uvedit_uv_deselect(scene, efa, tface, 2); + } + if(efa->v4 && BLI_in_rctf(&rectf, tface->uv[3][0], tface->uv[3][1])) { + if(select) uvedit_uv_select(scene, efa, tface, 3); + else uvedit_uv_deselect(scene, efa, tface, 3); + } + } + else if(pinned) { + if((tface->unwrap & TF_PIN1) && + BLI_in_rctf(&rectf, tface->uv[0][0], tface->uv[0][1])) { + + if(select) uvedit_uv_select(scene, efa, tface, 0); + else uvedit_uv_deselect(scene, efa, tface, 0); + } + if((tface->unwrap & TF_PIN2) && + BLI_in_rctf(&rectf, tface->uv[1][0], tface->uv[1][1])) { + + if(select) uvedit_uv_select(scene, efa, tface, 1); + else uvedit_uv_deselect(scene, efa, tface, 1); + } + if((tface->unwrap & TF_PIN3) && + BLI_in_rctf(&rectf, tface->uv[2][0], tface->uv[2][1])) { + + if(select) uvedit_uv_select(scene, efa, tface, 2); + else uvedit_uv_deselect(scene, efa, tface, 2); + } + if((efa->v4) && (tface->unwrap & TF_PIN4) && BLI_in_rctf(&rectf, tface->uv[3][0], tface->uv[3][1])) { + if(select) uvedit_uv_select(scene, efa, tface, 3); + else uvedit_uv_deselect(scene, efa, tface, 3); } } } } - if(ok) { - /* make sure newly selected vert selection is updated*/ - if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) { - if(scene->selectmode != SCE_SELECT_FACE) { - if(select) EM_select_flush(em); - else EM_deselect_flush(em); - } + } + + if(change) { + /* make sure newly selected vert selection is updated*/ + if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) { + if(scene->selectmode != SCE_SELECT_FACE) { + if(select) EM_select_flush(em); + else EM_deselect_flush(em); } - // XXX allqueue(REDRAWVIEW3D, 0); /* mesh selection has changed */ - - // XXX BIF_undo_push("Border select UV"); - // XXX scrarea_queue_winredraw(curarea); } + + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); + + return OPERATOR_FINISHED; + } + + return OPERATOR_CANCELLED; +} + +void UV_OT_border_select(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Border Select"; + ot->idname= "UV_OT_border_select"; + + /* api callbacks */ + ot->invoke= WM_border_select_invoke; + ot->exec= border_select_exec; + ot->modal= WM_border_select_modal; + ot->poll= ED_operator_uvedit; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + RNA_def_boolean(ot->srna, "pinned", 0, "Pinned", "Border select pinned UVs only."); + + RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX); + RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX); + RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX); + RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX); + RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX); +} + +/* ******************** circle select operator **************** */ + +static void select_uv_inside_ellipse(SpaceImage *sima, Scene *scene, int select, EditFace *efa, MTFace *tface, int index, float *offset, float *ell, int select_index) +{ + /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */ + float x, y, r2, *uv; + + uv= tface->uv[index]; + + x= (uv[0] - offset[0])*ell[0]; + y= (uv[1] - offset[1])*ell[1]; + + r2 = x*x + y*y; + if(r2 < 1.0) { + if(select) uvedit_uv_select(scene, efa, tface, select_index); + else uvedit_uv_deselect(scene, efa, tface, select_index); } } -int snap_uv_sel_to_curs(Scene *scene, Image *ima, Object *obedit, View2D *v2d) +int circle_select_exec(bContext *C, wmOperator *op) { + SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C); + Scene *scene= CTX_data_scene(C); + Object *obedit= CTX_data_edit_object(C); EditMesh *em= ((Mesh*)obedit->data)->edit_mesh; + ARegion *ar= CTX_wm_region(C); EditFace *efa; MTFace *tface; - short change = 0; + int x, y, radius, width, height, select; + float zoomx, zoomy, offset[2], ellipse[2]; + + /* get operator properties */ + select= (RNA_int_get(op->ptr, "event_type") == LEFTMOUSE); // XXX hardcoded + x= RNA_int_get(op->ptr, "x"); + y= RNA_int_get(op->ptr, "y"); + radius= RNA_int_get(op->ptr, "radius"); + + /* compute ellipse size and location, not a circle since we deal + * with non square image. ellipse is normalized, r = 1.0. */ + get_space_image_size(sima, &width, &height); + get_space_image_zoom(sima, ar, &zoomx, &zoomy); + + ellipse[0]= width*zoomx/radius; + ellipse[1]= height*zoomy/radius; + + UI_view2d_region_to_view(&ar->v2d, x, y, &offset[0], &offset[1]); + + /* do selection */ + for(efa= em->faces.first; efa; efa= efa->next) { + tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + select_uv_inside_ellipse(sima, scene, select, efa, tface, 0, offset, ellipse, 0); + select_uv_inside_ellipse(sima, scene, select, efa, tface, 1, offset, ellipse, 1); + select_uv_inside_ellipse(sima, scene, select, efa, tface, 2, offset, ellipse, 2); + if(efa->v4) + select_uv_inside_ellipse(sima, scene, select, efa, tface, 3, offset, ellipse, 3); + } + + if(select) EM_select_flush(em); + else EM_deselect_flush(em); + + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); + + return OPERATOR_FINISHED; +} + +void UV_OT_circle_select(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Circle Select"; + ot->idname= "UV_OT_circle_select"; + + /* api callbacks */ + ot->invoke= WM_gesture_circle_invoke; + ot->modal= WM_gesture_circle_modal; + ot->exec= circle_select_exec; + ot->poll= ED_operator_uvedit; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX); + RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX); + RNA_def_int(ot->srna, "radius", 0, INT_MIN, INT_MAX, "Radius", "", INT_MIN, INT_MAX); + RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX); +} + +/* ******************** snap cursor operator **************** */ + +static void snap_uv_to_pixel(float *uvco, float w, float h) +{ + uvco[0] = ((float)((int)((uvco[0]*w) + 0.5f)))/w; + uvco[1] = ((float)((int)((uvco[1]*h) + 0.5f)))/h; +} + +static void snap_cursor_to_pixels(SpaceImage *sima, View2D *v2d) +{ + int width= 0, height= 0; + + get_space_image_size(sima, &width, &height); + snap_uv_to_pixel(v2d->cursor, width, height); +} + +static int snap_cursor_to_selection(Scene *scene, Image *ima, Object *obedit, View2D *v2d) +{ + return uvedit_center(scene, ima, obedit, v2d->cursor, 0); +} + +static int snap_cursor_exec(bContext *C, wmOperator *op) +{ + SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C); + Scene *scene= CTX_data_scene(C); + Object *obedit= CTX_data_edit_object(C); + Image *ima= CTX_data_edit_image(C); + ARegion *ar= CTX_wm_region(C); + int change= 0; + + switch(RNA_boolean_get(op->ptr, "target")) { + case 0: + snap_cursor_to_pixels(sima, &ar->v2d); + change= 1; + break; + case 1: + change= snap_cursor_to_selection(scene, ima, obedit, &ar->v2d); + break; + } + + if(!change) + return OPERATOR_CANCELLED; + + ED_region_tag_redraw(ar); + + return OPERATOR_FINISHED; +} + +void UV_OT_snap_cursor(wmOperatorType *ot) +{ + static EnumPropertyItem target_items[] = { + {0, "PIXELS", "Pixels", ""}, + {1, "SELECTION", "Selection", ""}, + {0, NULL, NULL, NULL}}; + + /* identifiers */ + ot->name= "Snap Cursor"; + ot->idname= "UV_OT_snap_cursor"; + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* api callbacks */ + ot->exec= snap_cursor_exec; + ot->poll= ED_operator_uvedit; + + /* properties */ + RNA_def_enum(ot->srna, "target", target_items, 0, "Target", "Target to snap the selected UV's to."); +} + +/* ******************** snap selection operator **************** */ + +static int snap_uvs_to_cursor(Scene *scene, Image *ima, Object *obedit, View2D *v2d) +{ + EditMesh *em= ((Mesh*)obedit->data)->edit_mesh; + EditFace *efa; + MTFace *tface; + short change= 0; for(efa= em->faces.first; efa; efa= efa->next) { tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); @@ -2029,13 +2316,15 @@ int snap_uv_sel_to_curs(Scene *scene, Image *ima, Object *obedit, View2D *v2d) if(uvedit_uv_selected(scene, efa, tface, 2)) VECCOPY2D(tface->uv[2], v2d->cursor); if(efa->v4) if(uvedit_uv_selected(scene, efa, tface, 3)) VECCOPY2D(tface->uv[3], v2d->cursor); - change = 1; + + change= 1; } } + return change; } -int snap_uv_sel_to_adj_unsel(Scene *scene, Image *ima, Object *obedit) +static int snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object *obedit) { EditMesh *em= ((Mesh*)obedit->data)->edit_mesh; EditFace *efa; @@ -2054,12 +2343,14 @@ int snap_uv_sel_to_adj_unsel(Scene *scene, Image *ima, Object *obedit) * get unique indicies and to count how much to malloc */ for(efa= em->faces.first; efa; efa= efa->next) { tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + if(uvedit_face_visible(scene, ima, efa, tface)) { if(uvedit_uv_selected(scene, efa, tface, 0) && efa->v1->tmp.l==-1) efa->v1->tmp.l= count++; if(uvedit_uv_selected(scene, efa, tface, 1) && efa->v2->tmp.l==-1) efa->v2->tmp.l= count++; if(uvedit_uv_selected(scene, efa, tface, 2) && efa->v3->tmp.l==-1) efa->v3->tmp.l= count++; if(efa->v4) if(uvedit_uv_selected(scene, efa, tface, 3) && efa->v4->tmp.l==-1) efa->v4->tmp.l= count++; + change = 1; /* optional speedup */ @@ -2074,10 +2365,7 @@ int snap_uv_sel_to_adj_unsel(Scene *scene, Image *ima, Object *obedit) /* add all UV coords from visible, unselected UV coords as well as counting them to average later */ for(efa= em->faces.first; efa; efa= efa->next) { -// tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); -// if(uvedit_face_visible(scene, ima, efa, tface)) { if((tface=(MTFace *)efa->tmp.p)) { - /* is this an unselected UV we can snap to? */ if(efa->v1->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 0))) { coords[efa->v1->tmp.l*2] += tface->uv[0][0]; @@ -2118,8 +2406,6 @@ int snap_uv_sel_to_adj_unsel(Scene *scene, Image *ima, Object *obedit) /* copy the averaged unselected UVs back to the selected UVs */ for(efa= em->faces.first; efa; efa= efa->next) { -// tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); -// if(uvedit_face_visible(scene, ima, efa, tface)) { if((tface=(MTFace *)efa->tmp.p)) { if( uvedit_uv_selected(scene, efa, tface, 0) && @@ -2160,16 +2446,11 @@ int snap_uv_sel_to_adj_unsel(Scene *scene, Image *ima, Object *obedit) MEM_freeN(coords); MEM_freeN(usercount); - 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; + return change; } -int snap_uv_sel_to_pixels(SpaceImage *sima, Scene *scene, Object *obedit) /* warning, sanity checks must alredy be done */ +static int snap_uvs_to_pixels(SpaceImage *sima, Scene *scene, Object *obedit) { EditMesh *em= ((Mesh*)obedit->data)->edit_mesh; Image *ima= sima->image; @@ -2179,326 +2460,101 @@ int snap_uv_sel_to_pixels(SpaceImage *sima, Scene *scene, Object *obedit) /* war float w, h; short change = 0; - // XXX get_space_image_size(sima, &width, &height); + get_space_image_size(sima, &width, &height); w = (float)width; h = (float)height; for(efa= em->faces.first; efa; efa= efa->next) { tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); if(uvedit_face_visible(scene, ima, efa, tface)) { - if(uvedit_uv_selected(scene, efa, tface, 0)) snap_coord_to_pixel(tface->uv[0], w, h); - if(uvedit_uv_selected(scene, efa, tface, 1)) snap_coord_to_pixel(tface->uv[1], w, h); - if(uvedit_uv_selected(scene, efa, tface, 2)) snap_coord_to_pixel(tface->uv[2], w, h); + if(uvedit_uv_selected(scene, efa, tface, 0)) snap_uv_to_pixel(tface->uv[0], w, h); + if(uvedit_uv_selected(scene, efa, tface, 1)) snap_uv_to_pixel(tface->uv[1], w, h); + if(uvedit_uv_selected(scene, efa, tface, 2)) snap_uv_to_pixel(tface->uv[2], w, h); if(efa->v4) - if(uvedit_uv_selected(scene, efa, tface, 3)) snap_coord_to_pixel(tface->uv[3], w, h); + if(uvedit_uv_selected(scene, efa, tface, 3)) snap_uv_to_pixel(tface->uv[3], w, h); + change = 1; } } - return change; -} - -void snap_uv_curs_to_pixels(SpaceImage *sima, View2D *v2d) -{ - int width= 0, height= 0; - - // XXX get_space_image_size(sima, &width, &height); - snap_coord_to_pixel(v2d->cursor, width, height); -} -int snap_uv_curs_to_sel(Scene *scene, Image *ima, Object *obedit, View2D *v2d) -{ - if(!ED_uvedit_test(obedit)) return 0; - return uvedit_center(scene, ima, obedit, v2d->cursor, 0); + return change; } -void snap_menu_sima(SpaceImage *sima, Scene *scene, Object *obedit, View2D *v2d) +static int snap_selection_exec(bContext *C, wmOperator *op) { - short event; + SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C); + Scene *scene= CTX_data_scene(C); + Object *obedit= CTX_data_edit_object(C); + Image *ima= CTX_data_edit_image(C); + ARegion *ar= CTX_wm_region(C); + int change= 0; - if(!ED_uvedit_test(obedit) || !v2d) return; /* !G.v2d should never happen */ - - event = 0; // XXX pupmenu("Snap %t|Selection -> Pixels%x1|Selection -> Cursor%x2|Selection -> Adjacent Unselected%x3|Cursor -> Selection%x4|Cursor -> Pixel%x5"); - switch (event) { + switch(RNA_boolean_get(op->ptr, "target")) { + case 0: + change= snap_uvs_to_pixels(sima, scene, obedit); + break; case 1: - if(snap_uv_sel_to_pixels(sima, scene, obedit)) { - // XXX BIF_undo_push("Snap UV Selection to Pixels"); - DAG_object_flush_update(scene, obedit, OB_RECALC_DATA); - } - break; + change= snap_uvs_to_cursor(scene, ima, obedit, &ar->v2d); + break; case 2: - if(snap_uv_sel_to_curs(scene, sima->image, obedit, v2d)) { - // XXX BIF_undo_push("Snap UV Selection to Cursor"); - DAG_object_flush_update(scene, obedit, OB_RECALC_DATA); - } - break; - case 3: - if(snap_uv_sel_to_adj_unsel(scene, sima->image, obedit)) { - // XXX BIF_undo_push("Snap UV Selection to Cursor"); - DAG_object_flush_update(scene, obedit, OB_RECALC_DATA); - } - break; - case 4: - if(snap_uv_curs_to_sel(scene, sima->image, obedit, v2d)) - // XXX allqueue(REDRAWIMAGE, 0); - break; - case 5: - snap_uv_curs_to_pixels(sima, v2d); - // XXX scrarea_queue_winredraw(curarea); - 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 - * normalized to 1.0 - * Just for readability... - */ - -static void sel_uvco_inside_radius(SpaceImage *sima, Scene *scene, short sel, EditFace *efa, MTFace *tface, int index, float *offset, float *ell, short select_index) -{ - // 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 == 0 /* XXX LEFTMOUSE */) uvedit_uv_select(scene, efa, tface, select_index); - else uvedit_uv_deselect(scene, efa, tface, select_index); + change= snap_uvs_to_adjacent_unselected(scene, ima, obedit); + break; } -} - -// see below: -/** gets image dimensions of the 2D view 'v' */ -static void getSpaceImageDimension(SpaceImage *sima, ARegion *ar, float *xy) -{ - float zoomx= 0, zoomy= 0; - int width= 0, height= 0; - // XXX get_space_image_size(sima, &width, &height); - // XXX get_space_image_zoom(sima, ar, &zoomx, &zoomy); + if(!change) + return OPERATOR_CANCELLED; + + DAG_object_flush_update(scene, obedit, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit); - xy[0]= width*zoomx; - xy[1]= height*zoomy; + return OPERATOR_FINISHED; } -/** Callback function called by circle_selectCB to enable - * brush select in UV editor. - */ - -void uvedit_selectionCB(SpaceImage *sima, Scene *scene, ARegion *ar, short selecting, Object *obedit, short *mval, float rad) +void UV_OT_snap_selection(wmOperatorType *ot) { - EditMesh *em= ((Mesh*)obedit->data)->edit_mesh; - EditFace *efa; - float offset[2]; - MTFace *tface; - float ellipse[2]; // we need to deal with ellipses, as - // non square textures require for circle - // selection. this ellipse is normalized; r = 1.0 - - getSpaceImageDimension(sima, ar, ellipse); - ellipse[0] /= rad; - ellipse[1] /= rad; + static EnumPropertyItem target_items[] = { + {0, "PIXELS", "Pixels", ""}, + {1, "CURSOR", "Cursor", ""}, + {2, "ADJACENT_UNSELECTED", "Adjacent Unselected", ""}, + {0, NULL, NULL, NULL}}; - // XXX areamouseco_to_ipoco(G.v2d, mval, &offset[0], &offset[1]); + /* identifiers */ + ot->name= "Snap Selection"; + ot->idname= "UV_OT_snap_selection"; + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - if(selecting) { - for(efa= em->faces.first; efa; efa= efa->next) { - tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - sel_uvco_inside_radius(sima, scene, selecting, efa, tface, 0, offset, ellipse, 0); - sel_uvco_inside_radius(sima, scene, selecting, efa, tface, 1, offset, ellipse, 1); - sel_uvco_inside_radius(sima, scene, selecting, efa, tface, 2, offset, ellipse, 2); - if(efa->v4) - sel_uvco_inside_radius(sima, scene, selecting, efa, tface, 3, offset, ellipse, 3); - } + /* api callbacks */ + ot->exec= snap_selection_exec; + ot->poll= ED_operator_uvedit; - /* XXX */ -#if 0 - 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_uvs_sima(); - bglFlush(); - glDrawBuffer(GL_BACK); - } -#endif - - if(selecting == 0 /* XXX LEFTMOUSE */) EM_select_flush(em); - else EM_deselect_flush(em); - - if(sima->lock && (scene->toolsettings->uv_flag & UV_SYNC_SELECTION)) - ; // XXX force_draw_plus(SPACE_VIEW3D, 0); - } + /* properties */ + RNA_def_enum(ot->srna, "target", target_items, 0, "Target", "Target to snap the selected UV's to."); } -/* this function sets the selection on tagged faces - * This is needed because setting the selection on a face is done in - * a number of places but it also needs to respect the sticky modes - * for the UV verts - dealing with the sticky modes is best done in a seperate function - * - * de-selects faces that have been tagged on efa->tmp.l - */ -void uvface_setsel__internal(bContext *C, SpaceImage *sima, Scene *scene, Object *obedit, short select) -{ - - /* All functions calling this should call - * draw_uvs_face_check() - */ - - - /* selecting UV Faces with some modes requires us to change - * the selection in other faces (depending on the stickt mode) - * - * This only needs to be done when the Mesh is not used for selection - * (So for sticky modes - vertex or location based) - * */ - - EditMesh *em= ((Mesh*)obedit->data)->edit_mesh; - EditFace *efa; - MTFace *tf; - int nverts, i; - - if((scene->toolsettings->uv_flag & UV_SYNC_SELECTION)==0 && sima->sticky == SI_STICKY_VERTEX) { - /* tag all verts as untouched, - * then touch the ones that have a face center in the loop - * and select all MTFace UV's that use a touched vert */ - - EditVert *eve; - - for(eve= em->verts.first; eve; eve= eve->next) - eve->tmp.l = 0; - - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->tmp.l) { - if(efa->v4) - efa->v1->tmp.l= efa->v2->tmp.l= efa->v3->tmp.l= efa->v4->tmp.l=1; - else - efa->v1->tmp.l= efa->v2->tmp.l= efa->v3->tmp.l= 1; - } - } - /* now select tagged verts */ - for(efa= em->faces.first; efa; efa= efa->next) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - nverts= efa->v4? 4: 3; - for(i=0; i<nverts; i++) { - if((*(&efa->v1 + i))->tmp.l) { - if(select) - uvedit_uv_select(scene, efa, tf, i); - else - uvedit_uv_deselect(scene, efa, tf, i); - } - } - } - } else if((scene->toolsettings->uv_flag & UV_SYNC_SELECTION)==0 && sima->sticky == SI_STICKY_LOC) { - EditFace *efa_vlist; - MTFace *tf_vlist; - UvMapVert *start_vlist=NULL, *vlist_iter; - struct UvVertMap *vmap; - float limit[2]; - int efa_index; - //EditVert *eve; /* removed vert counting for now */ - //int a; - - uvedit_pixel_to_float(C, limit, 0.05); - - EM_init_index_arrays(em, 0, 0, 1); - vmap= EM_make_uv_vert_map(em, 0, 0, limit); - - /* verts are numbered above in make_uv_vert_map_EM, make sure this stays true! */ - /*for(a=0, eve= em->verts.first; eve; a++, eve= eve->next) - eve->tmp.l = a; */ - - if(vmap == NULL) - return; - - for(efa_index=0, efa= em->faces.first; efa; efa_index++, efa= efa->next) { - if(efa->tmp.l) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - nverts= efa->v4? 4: 3; - - for(i=0; i<nverts; i++) { - if(select) - uvedit_uv_select(scene, efa, tf, i); - else - uvedit_uv_deselect(scene, efa, tf, i); - - vlist_iter= EM_get_uv_map_vert(vmap, (*(&efa->v1 + i))->tmp.l); - - while (vlist_iter) { - if(vlist_iter->separate) - start_vlist = vlist_iter; - - if(efa_index == vlist_iter->f) - break; +/* ******************** pin operator **************** */ - vlist_iter = vlist_iter->next; - } - - vlist_iter = start_vlist; - while (vlist_iter) { - - if(vlist_iter != start_vlist && vlist_iter->separate) - break; - - if(efa_index != vlist_iter->f) { - efa_vlist = EM_get_face_for_index(vlist_iter->f); - tf_vlist = CustomData_em_get(&em->fdata, efa_vlist->data, CD_MTFACE); - - if(select) - uvedit_uv_select(scene, efa_vlist, tf_vlist, vlist_iter->tfindex); - else - uvedit_uv_deselect(scene, efa_vlist, tf_vlist, vlist_iter->tfindex); - } - vlist_iter = vlist_iter->next; - } - } - } - } - EM_free_index_arrays(); - EM_free_uv_vert_map(vmap); - - } - else { /* SI_STICKY_DISABLE or scene->toolsettings->uv_flag & UV_SYNC_SELECTION */ - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->tmp.l) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - if(select) - uvedit_face_select(scene, efa, tf); - else - uvedit_face_deselect(scene, efa, tf); - } - } - } -} - -void pin_tface_uv(Scene *scene, Image *ima, Object *obedit, int mode) +static int pin_exec(bContext *C, wmOperator *op) { + Scene *scene= CTX_data_scene(C); + Object *obedit= CTX_data_edit_object(C); + Image *ima= CTX_data_edit_image(C); EditMesh *em= ((Mesh*)obedit->data)->edit_mesh; EditFace *efa; MTFace *tface; - - if(!ED_uvedit_test(obedit)) return; + int clear= RNA_boolean_get(op->ptr, "clear"); for(efa= em->faces.first; efa; efa= efa->next) { tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + if(uvedit_face_visible(scene, ima, efa, tface)) { - if(mode ==1) { + if(!clear) { if(uvedit_uv_selected(scene, efa, tface, 0)) tface->unwrap |= TF_PIN1; if(uvedit_uv_selected(scene, efa, tface, 1)) tface->unwrap |= TF_PIN2; if(uvedit_uv_selected(scene, efa, tface, 2)) tface->unwrap |= TF_PIN3; if(efa->v4) if(uvedit_uv_selected(scene, efa, tface, 3)) tface->unwrap |= TF_PIN4; } - else if(mode ==0) { + else { if(uvedit_uv_selected(scene, efa, tface, 0)) tface->unwrap &= ~TF_PIN1; if(uvedit_uv_selected(scene, efa, tface, 1)) tface->unwrap &= ~TF_PIN2; if(uvedit_uv_selected(scene, efa, tface, 2)) tface->unwrap &= ~TF_PIN3; @@ -2508,20 +2564,40 @@ void pin_tface_uv(Scene *scene, Image *ima, Object *obedit, int mode) } } - // XXX BIF_undo_push("Pin UV"); - // XXX scrarea_queue_winredraw(curarea); + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit); + + return OPERATOR_FINISHED; +} + +void UV_OT_pin(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Pin"; + ot->idname= "UV_OT_pin"; + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* api callbacks */ + ot->exec= pin_exec; + ot->poll= ED_operator_uvedit; + + /* properties */ + RNA_def_boolean(ot->srna, "clear", 0, "Clear", "Clear pinning for the selection instead of setting it."); } -void select_pinned_tface_uv(Scene *scene, Image *ima, Object *obedit) +/* ******************** select pinned operator **************** */ + +static int select_pinned_exec(bContext *C, wmOperator *op) { + Scene *scene= CTX_data_scene(C); + Object *obedit= CTX_data_edit_object(C); + Image *ima= CTX_data_edit_image(C); EditMesh *em= ((Mesh*)obedit->data)->edit_mesh; EditFace *efa; MTFace *tface; - if(!ED_uvedit_test(obedit)) return; - for(efa= em->faces.first; efa; efa= efa->next) { tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + if(uvedit_face_visible(scene, ima, efa, tface)) { if(tface->unwrap & TF_PIN1) uvedit_uv_select(scene, efa, tface, 0); if(tface->unwrap & TF_PIN2) uvedit_uv_select(scene, efa, tface, 1); @@ -2529,16 +2605,24 @@ void select_pinned_tface_uv(Scene *scene, Image *ima, Object *obedit) if(efa->v4) { if(tface->unwrap & TF_PIN4) uvedit_uv_select(scene, efa, tface, 3); } - } } - if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) { - // XXX allqueue(REDRAWVIEW3D, 0); /* mesh selection has changed */ - } + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); + + return OPERATOR_FINISHED; +} + +void UV_OT_select_pinned(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Selected Pinned"; + ot->idname= "UV_OT_select_pinned"; + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - // XXX BIF_undo_push("Select Pinned UVs"); - // XXX scrarea_queue_winredraw(curarea); + /* api callbacks */ + ot->exec= select_pinned_exec; + ot->poll= ED_operator_uvedit; } /* ************************** registration **********************************/ @@ -2551,29 +2635,58 @@ void ED_operatortypes_uvedit(void) WM_operatortype_append(UV_OT_loop_select); WM_operatortype_append(UV_OT_select_linked); WM_operatortype_append(UV_OT_unlink_selection); + WM_operatortype_append(UV_OT_select_pinned); + WM_operatortype_append(UV_OT_border_select); + WM_operatortype_append(UV_OT_circle_select); + + WM_operatortype_append(UV_OT_snap_cursor); + WM_operatortype_append(UV_OT_snap_selection); WM_operatortype_append(UV_OT_align); WM_operatortype_append(UV_OT_mirror); WM_operatortype_append(UV_OT_stitch); WM_operatortype_append(UV_OT_weld); + WM_operatortype_append(UV_OT_pin); + + WM_operatortype_append(UV_OT_unwrap); + WM_operatortype_append(UV_OT_minimize_stretch); + WM_operatortype_append(UV_OT_average_islands_scale); + WM_operatortype_append(UV_OT_pack_islands); } void ED_keymap_uvedit(wmWindowManager *wm) { ListBase *keymap= WM_keymap_listbase(wm, "UVEdit", 0, 0); + /* pick selection */ WM_keymap_add_item(keymap, "UV_OT_select", SELECTMOUSE, KM_PRESS, 0, 0); RNA_boolean_set(WM_keymap_add_item(keymap, "UV_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "extend", 1); WM_keymap_add_item(keymap, "UV_OT_loop_select", SELECTMOUSE, KM_PRESS, KM_ALT, 0); // XXX not working? RNA_boolean_set(WM_keymap_add_item(keymap, "UV_OT_loop_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, KM_ALT)->ptr, "extend", 1); + /* border/circle selection */ + WM_keymap_add_item(keymap, "UV_OT_border_select", BKEY, KM_PRESS, 0, 0); + RNA_boolean_set(WM_keymap_add_item(keymap, "UV_OT_border_select", BKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "pinned", 1); + WM_keymap_add_item(keymap, "UV_OT_circle_select", CKEY, KM_PRESS, 0, 0); + + /* selection manipulation */ WM_keymap_add_item(keymap, "UV_OT_select_linked", LKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "UV_OT_unlink_selection", LKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "UV_OT_de_select_all", AKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "UV_OT_select_invert", IKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "UV_OT_select_pinned", PKEY, KM_PRESS, KM_SHIFT, 0); + /* uv operations */ WM_keymap_add_item(keymap, "UV_OT_stitch", VKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "UV_OT_pin", PKEY, KM_PRESS, 0, 0); + RNA_boolean_set(WM_keymap_add_item(keymap, "UV_OT_pin", PKEY, KM_PRESS, KM_ALT, 0)->ptr, "clear", 1); + + /* unwrap */ + WM_keymap_add_item(keymap, "UV_OT_unwrap", EKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "UV_OT_minimize_stretch", VKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "UV_OT_pack_islands", PKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "UV_OT_average_islands_scale", AKEY, KM_PRESS, KM_CTRL, 0); transform_keymap_for_space(wm, keymap, SPACE_IMAGE); } |