From 591ab657d609821b891303f638f9a482a8370640 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sat, 7 Feb 2009 01:27:46 +0000 Subject: 2.5: UV Editor, more operators. Border Select Circle Select Pin Select Pinned Unwrap Minimize Stretch Pack Islands Average Islands Scale Snap Cursor Snap Selection --- source/blender/editors/include/ED_mesh.h | 2 + source/blender/editors/include/ED_screen.h | 1 + source/blender/editors/include/UI_interface.h | 2 +- .../blender/editors/interface/interface_regions.c | 4 +- source/blender/editors/mesh/editmesh_mods.c | 22 +- source/blender/editors/screen/screen_ops.c | 14 + source/blender/editors/space_image/image_header.c | 110 +-- source/blender/editors/space_image/space_image.c | 1 + source/blender/editors/space_view3d/space_view3d.c | 1 + source/blender/editors/transform/transform.c | 4 +- source/blender/editors/uvedit/uvedit_intern.h | 5 +- source/blender/editors/uvedit/uvedit_ops.c | 1043 +++++++++++--------- source/blender/editors/uvedit/uvedit_unwrap_ops.c | 406 +++++--- 13 files changed, 911 insertions(+), 704 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 5a72ab201f4..bd997e93e9b 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -112,6 +112,8 @@ void EM_add_data_layer(struct EditMesh *em, struct CustomData *data, void EM_select_edge(struct EditEdge *eed, int sel); void EM_select_face(struct EditFace *efa, int sel); void EM_select_face_fgon(struct EditMesh *em, struct EditFace *efa, int val); +void EM_select_swap(struct EditMesh *em); +void EM_toggle_select_all(struct EditMesh *em); void EM_selectmode_flush(struct EditMesh *em); void EM_deselect_flush(struct EditMesh *em); void EM_selectmode_set(struct EditMesh *em); diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 068c0c888bf..122da322331 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -114,6 +114,7 @@ int ED_operator_editmesh(struct bContext *C); int ED_operator_editarmature(struct bContext *C); int ED_operator_editcurve(struct bContext *C); int ED_operator_uvedit(struct bContext *C); +int ED_operator_uvmap(struct bContext *C); int ED_operator_posemode(struct bContext *C); diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 9f832a3db30..575654f49b1 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -212,7 +212,7 @@ void uiMenuContext(uiMenuItem *head, int opcontext); void uiMenuItemVal(uiMenuItem *head, const char *name, int icon, int argval); void uiMenuItemEnumO(uiMenuItem *head, int icon, char *opname, char *propname, int value); -void uiMenuItemBooleanO(uiMenuItem *head, int icon, char *opname, char *propname, int value); +void uiMenuItemBooleanO(uiMenuItem *head, const char *name, int icon, char *opname, char *propname, int value); void uiMenuItemsEnumO(uiMenuItem *head, char *opname, char *propname); void uiMenuItemIntO(uiMenuItem *head, const char *name, int icon, char *opname, char *propname, int value); void uiMenuItemFloatO(uiMenuItem *head, const char *name, int icon, char *opname, char *propname, float value); diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index ffd742098de..eadb3f9b2aa 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -2035,9 +2035,9 @@ void uiMenuItemFloatO(uiMenuItem *head, const char *name, int icon, char *opname } /* single operator item with property */ -void uiMenuItemBooleanO(uiMenuItem *head, int icon, char *opname, char *propname, int value) +void uiMenuItemBooleanO(uiMenuItem *head, const char *name, int icon, char *opname, char *propname, int value) { - uiMenuItem *item= ui_menu_add_item(head, "", icon, 0); + uiMenuItem *item= ui_menu_add_item(head, name, icon, 0); item->opname= opname; // static! item->propname= propname; // static! diff --git a/source/blender/editors/mesh/editmesh_mods.c b/source/blender/editors/mesh/editmesh_mods.c index 8870894df4b..77fa456a76c 100644 --- a/source/blender/editors/mesh/editmesh_mods.c +++ b/source/blender/editors/mesh/editmesh_mods.c @@ -3354,7 +3354,7 @@ void MESH_OT_select_non_manifold(wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } -static void selectswap_mesh(EditMesh *em) /* UI level */ +void EM_select_swap(EditMesh *em) /* exported for UV */ { EditVert *eve; EditEdge *eed; @@ -3395,7 +3395,7 @@ static int selectswap_mesh_exec(bContext *C, wmOperator *op) Object *obedit= CTX_data_edit_object(C); EditMesh *em= ((Mesh *)obedit->data)->edit_mesh; - selectswap_mesh(em); + EM_select_swap(em); WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); return OPERATOR_FINISHED; @@ -3417,21 +3417,23 @@ void MESH_OT_select_invert(wmOperatorType *ot) /* ******************** (de)select all operator **************** */ +void EM_toggle_select_all(EditMesh *em) /* exported for UV */ +{ + if(EM_nvertices_selected(em)) + EM_clear_flag_all(em, SELECT); + else + EM_set_flag_all(em, SELECT); +} + static int toggle_select_all_exec(bContext *C, wmOperator *op) { Object *obedit= CTX_data_edit_object(C); EditMesh *em= ((Mesh *)obedit->data)->edit_mesh; - if( EM_nvertices_selected(em) ) { - EM_clear_flag_all(em, SELECT); - } - else { - EM_set_flag_all(em, SELECT); - } - -// if (EM_texFaceCheck()) + EM_toggle_select_all(em); WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); + return OPERATOR_FINISHED; } diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 2e7df0d71c1..028c0105f11 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -210,6 +210,20 @@ int ED_operator_uvedit(bContext *C) return 0; } +int ED_operator_uvmap(bContext *C) +{ + Object *obedit= CTX_data_edit_object(C); + EditMesh *em= NULL; + + if(obedit && obedit->type==OB_MESH) + em= ((Mesh *)obedit->data)->edit_mesh; + + if(em && (em->faces.first)) + return 1; + + return 0; +} + int ED_operator_editcurve(bContext *C) { Object *obedit= CTX_data_edit_object(C); diff --git a/source/blender/editors/space_image/image_header.c b/source/blender/editors/space_image/image_header.c index f1c80ed8531..7f9171e87b3 100644 --- a/source/blender/editors/space_image/image_header.c +++ b/source/blender/editors/space_image/image_header.c @@ -160,39 +160,21 @@ static void image_viewmenu(bContext *C, uiMenuItem *head, void *arg_unused) else uiMenuItemO(head, 0, "SCREEN_OT_screen_full_area"); // "Maximize Window", Ctr DownArrow } -#if 0 -static void do_selectmenu(bContext *C, void *arg, int event) -{ - switch(event) - { - case 0: /* Border Select */ - borderselect_sima(UV_SELECT_ALL); - break; - case 8: /* Border Select Pinned */ - borderselect_sima(UV_SELECT_PINNED); - break; - case 7: /* Pinned UVs */ - select_pinned_tface_uv(); - break; - } -} -#endif - static void image_selectmenu(bContext *C, uiMenuItem *head, void *arg_unused) { - uiMenuItemO(head, 0, "UV_OT_border_select"); // Border Select|B - uiMenuItemO(head, 0, "UV_OT_border_select_pinned"); // Border Select Pinned|Shift B + uiMenuItemO(head, 0, "UV_OT_border_select"); + uiMenuItemBooleanO(head, "Border Select Pinned", 0, "UV_OT_border_select", "pinned", 1); // Border Select Pinned|Shift B uiMenuSeparator(head); uiMenuItemO(head, 0, "UV_OT_de_select_all"); uiMenuItemO(head, 0, "UV_OT_select_invert"); - uiMenuItemO(head, 0, "UV_OT_unlink_selection"); // Unlink Selection|Alt L + uiMenuItemO(head, 0, "UV_OT_unlink_selection"); uiMenuSeparator(head); - uiMenuItemO(head, 0, "UV_OT_select_pinned"); // Select Pinned|Shift P - uiMenuItemO(head, 0, "UV_OT_select_linked"); // Select Linked|Ctrl L + uiMenuItemO(head, 0, "UV_OT_select_pinned"); + uiMenuItemO(head, 0, "UV_OT_select_linked"); } #if 0 @@ -376,59 +358,12 @@ static void image_uvs_transformmenu(bContext *C, uiMenuItem *head, void *arg_unu uiMenuItemO(head, 0, "UV_OT_scale"); // Scale|S } -#if 0 -static void do_image_uvs_mirrormenu(void *arg, int event) -{ - float mat[3][3]; - - Mat3One(mat); - - switch(event) { - case 0: /* X axis */ - initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM); - BIF_setSingleAxisConstraint(mat[0], " on global X axis"); - Transform(); - break; - case 1: /* Y axis */ - initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM); - BIF_setSingleAxisConstraint(mat[1], " on global Y axis"); - Transform(); - break; - } - - BIF_undo_push("Mirror UV"); -} -#endif - static void image_uvs_mirrormenu(bContext *C, uiMenuItem *head, void *arg_unused) { uiMenuItemEnumO(head, 0, "UV_OT_mirror", "axis", 'x'); // "X Axis", M, 1 uiMenuItemEnumO(head, 0, "UV_OT_mirror", "axis", 'y'); // "Y Axis", M, 2 } -#if 0 -static void do_image_uvs_weldalignmenu(void *arg, int event) -{ - switch(event) { - case 0: /* Weld */ - weld_align_tface_uv('w'); - break; - case 1: /* Align Auto */ - weld_align_tface_uv('a'); - break; - case 2: /* Align X */ - weld_align_tface_uv('x'); - break; - case 3: /* Align Y */ - weld_align_tface_uv('y'); - break; - } - - if(event==0) BIF_undo_push("Weld UV"); - else if(ELEM3(event, 1, 2, 3)) BIF_undo_push("Align UV"); -} -#endif - static void image_uvs_weldalignmenu(bContext *C, uiMenuItem *head, void *arg_unused) { uiMenuItemO(head, 0, "UV_OT_weld"); // W, 1 @@ -474,32 +409,9 @@ static void image_uvs_scriptsmenu (void *args_unused) static void do_uvsmenu(bContext *C, void *arg, int event) { switch(event) { - case 2: /* UVs Clipped to Image Size */ - if(sima->flag & SI_CLIP_UV) sima->flag &= ~SI_CLIP_UV; - else sima->flag |= SI_CLIP_UV; - break; - case 5: /* Proportional Edit (toggle) */ - if(G.scene->proportional) - G.scene->proportional= 0; - else - G.scene->proportional= 1; - break; - case 7: /* UVs Snap to Pixel */ - sima->flag ^= SI_PIXELSNAP; - break; - case 8: - pin_tface_uv(1); - break; - case 9: - pin_tface_uv(0); - break; case 10: unwrap_lscm(0); break; - case 11: - if(sima->flag & SI_LIVE_UNWRAP) sima->flag &= ~SI_LIVE_UNWRAP; - else sima->flag |= SI_LIVE_UNWRAP; - break; case 12: minimize_stretch_tface_uv(); break; @@ -536,15 +448,15 @@ static void image_uvsmenu(bContext *C, uiMenuItem *head, void *arg_unused) uiMenuSeparator(head); uiMenuItemBooleanR(head, &uvptr, "live_unwrap"); - uiMenuItemO(head, 0, "UV_OT_unwrap"); // Unwrap|E - uiMenuItemO(head, 0, "UV_OT_unpin"); // Unpin|Alt P - uiMenuItemO(head, 0, "UV_OT_pin"); // Pin|P + uiMenuItemO(head, 0, "UV_OT_unwrap"); + uiMenuItemBooleanO(head, "Unpin", 0, "UV_OT_pin", "clear", 1); + uiMenuItemO(head, 0, "UV_OT_pin"); uiMenuSeparator(head); - uiMenuItemO(head, 0, "UV_OT_pack_islands"); // Pack Islands|Ctr P - uiMenuItemO(head, 0, "UV_OT_average_islands"); // Average Islands Scale|Ctrl A - uiMenuItemO(head, 0, "UV_OT_minimize_stretch"); // Minimize Stretch...|Ctrl V + uiMenuItemO(head, 0, "UV_OT_pack_islands"); + uiMenuItemO(head, 0, "UV_OT_average_islands_scale"); + uiMenuItemO(head, 0, "UV_OT_minimize_stretch"); uiMenuItemO(head, 0, "UV_OT_stitch"); uiMenuSeparator(head); diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 0b42fb0d621..19ba040ea8c 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -387,6 +387,7 @@ static void image_main_area_listener(ARegion *ar, wmNotifier *wmn) case NC_OBJECT: switch(wmn->data) { case ND_GEOM_SELECT: + case ND_GEOM_DATA: ED_region_tag_redraw(ar); break; } diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index a87506fc5eb..7e209bc8693 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -302,6 +302,7 @@ static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn) case ND_BONE_SELECT: case ND_TRANSFORM: case ND_GEOM_SELECT: + case ND_GEOM_DATA: case ND_DRAW: case ND_MODIFIER: case ND_KEYS: diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 39fa4ed815b..76c4721003b 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -366,14 +366,14 @@ static void viewRedrawForce(bContext *C, TransInfo *t) WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, NULL); } else if (t->spacetype==SPACE_IMAGE) { + // XXX how to deal with lock? #if 0 SpaceImage *sima= (SpaceImage*)t->sa->spacedata.first; if(sima->lock) force_draw_plus(SPACE_VIEW3D, 0); else force_draw(0); #endif - // XXX better notifier, and how to deal with lock? - WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, t->obedit); + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, t->obedit); } } diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h index eb58562239e..a66c9ea2fb8 100644 --- a/source/blender/editors/uvedit/uvedit_intern.h +++ b/source/blender/editors/uvedit/uvedit_intern.h @@ -66,7 +66,10 @@ float uv_area(float uv[][2], int quad); void uv_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy); /* operators */ -void UV_OT_de_select_all(struct wmOperatorType *ot); +void UV_OT_pack_islands(struct wmOperatorType *ot); +void UV_OT_unwrap(struct wmOperatorType *ot); +void UV_OT_minimize_stretch(struct wmOperatorType *ot); +void UV_OT_average_islands_scale(struct wmOperatorType *ot); #endif /* ED_UVEDIT_INTERN_H */ 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; iv1 + 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; iv1 + 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; iv1 + 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; iv1 + 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); } diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index de5838823d1..c7e0dfd7bc7 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -40,6 +40,7 @@ #include "DNA_screen_types.h" #include "DNA_space_types.h" +#include "BKE_context.h" #include "BKE_customdata.h" #include "BKE_depsgraph.h" #include "BKE_global.h" @@ -53,12 +54,44 @@ #include "PIL_time.h" #include "ED_mesh.h" +#include "ED_screen.h" #include "ED_uvedit.h" +#include "RNA_access.h" +#include "RNA_define.h" + +#include "WM_api.h" +#include "WM_types.h" + #include "uvedit_intern.h" #include "uvedit_parametrizer.h" -/* Parametrizer */ +static void ED_uvedit_create_uvs(EditMesh *em) +{ +#if 0 + if (em && em->faces.first) + EM_add_data_layer(&em->fdata, CD_MTFACE); + + if (!ED_uvedit_test(obedit)) + return; + + if (G.sima && G.sima->image) /* this is a bit of a kludge, but assume they want the image on their mesh when UVs are added */ + image_changed(G.sima, G.sima->image); + + /* select new UV's */ + if ((G.sima==0 || G.sima->flag & SI_SYNC_UVSEL)==0) { + EditFace *efa; + MTFace *tf; + for(efa=em->faces.first; efa; efa=efa->next) { + tf= (MTFace *)CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + simaFaceSel_Set(efa, tf); + } + } +#endif +} + +/****************** Parametrizer Conversion ***************/ + ParamHandle *construct_param_handle(Scene *scene, EditMesh *em, short implicit, short fill, short sel) { ParamHandle *handle; @@ -70,13 +103,14 @@ ParamHandle *construct_param_handle(Scene *scene, EditMesh *em, short implicit, handle = param_construct_begin(); - if ((scene->toolsettings->uvcalc_flag & UVCALC_NO_ASPECT_CORRECT)==0) { + if((scene->toolsettings->uvcalc_flag & UVCALC_NO_ASPECT_CORRECT)==0) { efa = EM_get_actFace(em, 1); if (efa) { float aspx = 1.0f, aspy= 1.0f; // XXX MTFace *tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); // XXX image_final_aspect(tf->tpage, &aspx, &aspy); + // XXX get_space_image_aspect(sima, &aspx, &aspy); if (aspx!=aspy) param_aspect_ratio(handle, aspx, aspy); @@ -159,40 +193,24 @@ ParamHandle *construct_param_handle(Scene *scene, EditMesh *em, short implicit, return handle; } -void unwrap_lscm(Scene *scene, Object *obedit, short seamcut) +/* ******************** unwrap operator **************** */ + +static int unwrap_exec(bContext *C, wmOperator *op) { + Scene *scene= CTX_data_scene(C); + Object *obedit= CTX_data_edit_object(C); EditMesh *em= ((Mesh*)obedit->data)->edit_mesh; ParamHandle *handle; - short abf = scene->toolsettings->unwrapper == 1; - short fillholes = scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES; + int method = RNA_enum_get(op->ptr, "method"); + int fill_holes = RNA_boolean_get(op->ptr, "fill_holes"); - /* add uvs if there not here */ - if (!ED_uvedit_test(obedit)) { -#if 0 - if (em && em->faces.first) - EM_add_data_layer(&em->fdata, CD_MTFACE); - - if (!ED_uvedit_test(obedit)) - return; - - if (G.sima && G.sima->image) /* this is a bit of a kludge, but assume they want the image on their mesh when UVs are added */ - image_changed(G.sima, G.sima->image); - - /* select new UV's */ - if ((G.sima==0 || G.sima->flag & SI_SYNC_UVSEL)==0) { - EditFace *efa; - MTFace *tf; - for(efa=em->faces.first; efa; efa=efa->next) { - tf= (MTFace *)CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - simaFaceSel_Set(efa, tf); - } - } -#endif - } + /* add uvs if they don't exist yet */ + if(!ED_uvedit_test(obedit)) + ED_uvedit_create_uvs(em); - handle = construct_param_handle(scene, em, 0, fillholes, seamcut == 0); + handle= construct_param_handle(scene, em, 0, fill_holes, 0); - param_lscm_begin(handle, PARAM_FALSE, abf); + param_lscm_begin(handle, PARAM_FALSE, method == 0); param_lscm_solve(handle); param_lscm_end(handle); @@ -202,151 +220,291 @@ void unwrap_lscm(Scene *scene, Object *obedit, short seamcut) param_delete(handle); - if (!seamcut) - ; // XXX BIF_undo_push("UV unwrap"); - DAG_object_flush_update(scene, obedit, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit); - // XXX allqueue(REDRAWVIEW3D, 0); - // XXX allqueue(REDRAWIMAGE, 0); + return OPERATOR_FINISHED; } -void minimize_stretch_tface_uv(Scene *scene, Object *obedit) +void UV_OT_unwrap(wmOperatorType *ot) { - EditMesh *em= ((Mesh*)obedit->data)->edit_mesh; + static EnumPropertyItem method_items[] = { + {0, "ANGLE_BASED", "Angle Based", ""}, + {1, "CONFORMAL", "Conformal", ""}, + {0, NULL, NULL, NULL}}; + + /* identifiers */ + ot->name= "Unwrap"; + ot->idname= "UV_OT_unwrap"; + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* api callbacks */ + ot->exec= unwrap_exec; + ot->poll= ED_operator_uvmap; + + /* properties */ + RNA_def_enum(ot->srna, "method", method_items, 0, "Method", "Unwrapping method. Angle Based usually gives better results than Conformal, while being somewhat slower."); + RNA_def_boolean(ot->srna, "fill_holes", 1, "Fill Holes", "Virtual fill holes in mesh before unwrapping, to better avoid overlaps and preserve symmetry."); +} + +/* ******************** minimize stretch operator **************** */ + +typedef struct MinStretch { + Scene *scene; + Object *obedit; + EditMesh *em; ParamHandle *handle; + float blend; double lasttime; - short doit = 1, escape = 0, val, blend = 0; - unsigned short event = 0; - short fillholes = scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES; - - if(!ED_uvedit_test(obedit)) return; + int i, iterations; + wmTimer *timer; +} MinStretch; - handle = construct_param_handle(scene, em, 1, fillholes, 1); +static void minimize_stretch_init(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + Object *obedit= CTX_data_edit_object(C); + EditMesh *em= ((Mesh*)obedit->data)->edit_mesh; + MinStretch *ms; + int fill_holes= RNA_boolean_get(op->ptr, "fill_holes"); + + ms= MEM_callocN(sizeof(MinStretch), "MinStretch"); + ms->scene= scene; + ms->obedit= obedit; + ms->em= em; + ms->blend= RNA_float_get(op->ptr, "blend"); + ms->iterations= RNA_int_get(op->ptr, "iterations"); + ms->handle= construct_param_handle(scene, em, 1, fill_holes, 1); + ms->lasttime= PIL_check_seconds_timer(); + + param_stretch_begin(ms->handle); + if(ms->blend != 0.0f) + param_stretch_blend(ms->handle, ms->blend); + + op->customdata= ms; +} - lasttime = PIL_check_seconds_timer(); +static void minimize_stretch_iteration(bContext *C, wmOperator *op, int interactive) +{ + MinStretch *ms= op->customdata; + ScrArea *sa= CTX_wm_area(C); - param_stretch_begin(handle); + param_stretch_blend(ms->handle, ms->blend); + param_stretch_iter(ms->handle); - while (doit) { - param_stretch_iter(handle); + if(interactive && (PIL_check_seconds_timer() - ms->lasttime > 0.5)) { + char str[100]; - while (0) { // XXX qtest()) { - event= 0; // XXX extern_qread(&val); + param_flush(ms->handle); - if (val) { -#if 0 - switch (event) { - case ESCKEY: - escape = 1; - case RETKEY: - case PADENTER: - doit = 0; - break; - case PADPLUSKEY: - case WHEELUPMOUSE: - if (blend < 10) { - blend++; - param_stretch_blend(handle, blend*0.1f); - param_flush(handle); - lasttime = 0.0f; - } - break; - case PADMINUS: - case WHEELDOWNMOUSE: - if (blend > 0) { - blend--; - param_stretch_blend(handle, blend*0.1f); - param_flush(handle); - lasttime = 0.0f; - } - break; - } -#endif - } - else if (0) { // XXX (event == LEFTMOUSE) || (event == RIGHTMOUSE)) { - escape = 0; // XXX (event == RIGHTMOUSE); - doit = 0; - } + if(sa) { + sprintf(str, "Minimize Stretch. Blend %.2f.", ms->blend); + ED_area_headerprint(sa, str); } - - if (!doit) - break; - if (PIL_check_seconds_timer() - lasttime > 0.5) { - char str[100]; + ms->lasttime = PIL_check_seconds_timer(); - param_flush(handle); + DAG_object_flush_update(ms->scene, ms->obedit, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ms->obedit); + } +} - sprintf(str, "Stretch minimize. Blend %.2f.", blend*0.1f); - // XXX headerprint(str); +static void minimize_stretch_exit(bContext *C, wmOperator *op, int cancel) +{ + MinStretch *ms= op->customdata; + ScrArea *sa= CTX_wm_area(C); - lasttime = PIL_check_seconds_timer(); - DAG_object_flush_update(scene, obedit, OB_RECALC_DATA); - // XXX if(G.sima->lock) force_draw_plus(SPACE_VIEW3D, 0); - // XXX else force_draw(0); - } - } + if(sa) + ED_area_headerprint(sa, NULL); + if(ms->timer) + WM_event_remove_window_timer(CTX_wm_window(C), ms->timer); - if (escape) - param_flush_restore(handle); + if(cancel) + param_flush_restore(ms->handle); else - param_flush(handle); + param_flush(ms->handle); - param_stretch_end(handle); + param_stretch_end(ms->handle); + param_delete(ms->handle); - param_delete(handle); + DAG_object_flush_update(ms->scene, ms->obedit, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ms->obedit); - // XXX BIF_undo_push("UV stretch minimize"); + MEM_freeN(ms); + op->customdata= NULL; +} - DAG_object_flush_update(scene, obedit, OB_RECALC_DATA); +static int minimize_stretch_exec(bContext *C, wmOperator *op) +{ + int i, iterations; + + minimize_stretch_init(C, op); + + iterations= RNA_int_get(op->ptr, "iterations"); + for(i=0; icustomdata; + WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + ms->timer= WM_event_add_window_timer(CTX_wm_window(C), TIMER, 0.01f); + + return OPERATOR_RUNNING_MODAL; +} + +static int minimize_stretch_modal(bContext *C, wmOperator *op, wmEvent *event) +{ + MinStretch *ms= op->customdata; + + switch(event->type) { + case ESCKEY: + case RIGHTMOUSE: + minimize_stretch_exit(C, op, 1); + return OPERATOR_CANCELLED; + case RETKEY: + case PADENTER: + case LEFTMOUSE: + minimize_stretch_exit(C, op, 0); + return OPERATOR_FINISHED; + case PADPLUSKEY: + case WHEELUPMOUSE: + if(ms->blend < 0.95f) { + ms->blend += 0.1f; + ms->lasttime= 0.0f; + RNA_float_set(op->ptr, "blend", ms->blend); + minimize_stretch_iteration(C, op, 1); + } + break; + case PADMINUS: + case WHEELDOWNMOUSE: + if(ms->blend > 0.05f) { + ms->blend -= 0.1f; + ms->lasttime= 0.0f; + RNA_float_set(op->ptr, "blend", ms->blend); + minimize_stretch_iteration(C, op, 1); + } + break; + case TIMER: + if(ms->timer == event->customdata) { + double start= PIL_check_seconds_timer(); - // XXX allqueue(REDRAWVIEW3D, 0); - // XXX allqueue(REDRAWIMAGE, 0); + do { + minimize_stretch_iteration(C, op, 1); + } while(PIL_check_seconds_timer() - start < 0.01); + } + break; + } + + if(ms->iterations && ms->i >= ms->iterations) { + minimize_stretch_exit(C, op, 0); + return OPERATOR_FINISHED; + } + + return OPERATOR_RUNNING_MODAL; } -void pack_charts_tface_uv(Scene *scene, Object *obedit) +static int minimize_stretch_cancel(bContext *C, wmOperator *op) { + minimize_stretch_exit(C, op, 1); + + return OPERATOR_CANCELLED; +} + +void UV_OT_minimize_stretch(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Minimize Stretch"; + ot->idname= "UV_OT_minimize_stretch"; + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* api callbacks */ + ot->exec= minimize_stretch_exec; + ot->invoke= minimize_stretch_invoke; + ot->modal= minimize_stretch_modal; + ot->cancel= minimize_stretch_cancel; + ot->poll= ED_operator_uvedit; + + /* properties */ + RNA_def_boolean(ot->srna, "fill_holes", 1, "Fill Holes", "Virtual fill holes in mesh before unwrapping, to better avoid overlaps and preserve symmetry."); + RNA_def_float(ot->srna, "blend", 0.0f, 0.0f, 1.0f, "Blend", "Blend factor between stretch minimized and original.", 0.0f, 1.0f); + RNA_def_int(ot->srna, "iterations", 0, 0, INT_MAX, "Iterations", "Number of iterations to run, 0 is unlimited when run interactively.", 0, 100); +} + +/* ******************** pack islands operator **************** */ + +static int pack_islands_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + Object *obedit= CTX_data_edit_object(C); EditMesh *em= ((Mesh*)obedit->data)->edit_mesh; ParamHandle *handle; - - if(!ED_uvedit_test(obedit)) return; handle = construct_param_handle(scene, em, 1, 0, 1); param_pack(handle); param_flush(handle); param_delete(handle); - - // XXX BIF_undo_push("UV pack islands"); - + DAG_object_flush_update(scene, obedit, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit); - // XXX allqueue(REDRAWVIEW3D, 0); - // XXX allqueue(REDRAWIMAGE, 0); + return OPERATOR_FINISHED; } +void UV_OT_pack_islands(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Pack Islands"; + ot->idname= "UV_OT_pack_islands"; + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* api callbacks */ + ot->exec= pack_islands_exec; + ot->poll= ED_operator_uvedit; +} + +/* ******************** average islands scale operator **************** */ -void average_charts_tface_uv(Scene *scene, Object *obedit) +static int average_islands_scale_exec(bContext *C, wmOperator *op) { + Scene *scene= CTX_data_scene(C); + Object *obedit= CTX_data_edit_object(C); EditMesh *em= ((Mesh*)obedit->data)->edit_mesh; ParamHandle *handle; - - if(!ED_uvedit_test(obedit)) return; - handle = construct_param_handle(scene, em, 1, 0, 1); + handle= construct_param_handle(scene, em, 1, 0, 1); param_average(handle); param_flush(handle); param_delete(handle); - - // XXX BIF_undo_push("UV average island scale"); - + DAG_object_flush_update(scene, obedit, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit); + + return OPERATOR_FINISHED; +} - // XXX allqueue(REDRAWVIEW3D, 0); - // XXX allqueue(REDRAWIMAGE, 0); +void UV_OT_average_islands_scale(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Average Islands Scale"; + ot->idname= "UV_OT_average_islands_scale"; + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* api callbacks */ + ot->exec= average_islands_scale_exec; + ot->poll= ED_operator_uvedit; } -/* LSCM live mode */ +/**************** Live Unwrap *****************/ static ParamHandle *liveHandle = NULL; -- cgit v1.2.3