diff options
author | Campbell Barton <ideasman42@gmail.com> | 2009-10-22 23:17:46 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2009-10-22 23:17:46 +0400 |
commit | e8af794441bbce7ef49d872e8c3b2c2b7971e0e6 (patch) | |
tree | 5c0edc873c6dbfc73ff6884738317c7523fa7639 /source/blender | |
parent | e2b74dc7364a11b5328954b6a49a46cd44dfbd2e (diff) |
face mask mode
- border select
- linked selection (Ctrl+L)
- select all
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/editors/include/ED_mesh.h | 4 | ||||
-rw-r--r-- | source/blender/editors/mesh/editface.c | 242 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_image.c | 3 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_intern.h | 4 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_ops.c | 15 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_utils.c | 68 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/space_view3d.c | 3 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_select.c | 2 |
8 files changed, 272 insertions, 69 deletions
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 991f87707c8..8c7e0bf607a 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -53,6 +53,7 @@ struct UvMapVert; struct CustomData; struct Material; struct Object; +struct recti; #define EM_FGON_DRAW 1 // face flag #define EM_FGON 2 // edge and face flag both @@ -166,6 +167,9 @@ void EM_automerge(struct Scene *scene, struct Object *obedit, int update); /* editface.c */ struct MTFace *EM_get_active_mtface(struct EditMesh *em, struct EditFace **act_efa, struct MCol **mcol, int sloppy); int face_select(struct bContext *C, struct Object *ob, short mval[2], int extend); +void face_borderselect(struct bContext *C, struct Object *ob, struct rcti *rect, int select); +void deselectall_tface(struct Object *ob); +void select_linked_tfaces(struct bContext *C, struct Object *ob, short mval[2], int mode); /* object_vgroup.c */ diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index 3b15593916c..0042ad9483b 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -60,6 +60,7 @@ #include "BKE_texture.h" #include "BKE_utildefines.h" #include "BKE_customdata.h" +#include "BKE_context.h" #include "BIF_gl.h" #include "BIF_glutil.h" @@ -72,6 +73,7 @@ #endif #include "ED_mesh.h" +#include "ED_screen.h" #include "ED_object.h" #include "ED_view3d.h" @@ -82,7 +84,6 @@ #include "mesh_intern.h" /* ***************** XXX **************** */ -static void error() {} static int pupmenu() {return 0;} /* ***************** XXX **************** */ @@ -234,35 +235,156 @@ void hide_tface(Scene *scene) // XXX notifier! object_tface_flags_changed(OBACT, 0); } -void select_linked_tfaces(Scene *scene, View3D *v3d, int mode) +/* Set tface seams based on edge data, uses hash table to find seam edges. */ + +static void hash_add_face(EdgeHash *ehash, MFace *mf) +{ + BLI_edgehash_insert(ehash, mf->v1, mf->v2, NULL); + BLI_edgehash_insert(ehash, mf->v2, mf->v3, NULL); + if(mf->v4) { + BLI_edgehash_insert(ehash, mf->v3, mf->v4, NULL); + BLI_edgehash_insert(ehash, mf->v4, mf->v1, NULL); + } + else + BLI_edgehash_insert(ehash, mf->v3, mf->v1, NULL); +} + + +void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int index) +{ + MFace *mf; + int a, doit=1, mark=0; + char *linkflag; + EdgeHash *ehash, *seamhash; + MEdge *med; + + ehash= BLI_edgehash_new(); + seamhash = BLI_edgehash_new(); + linkflag= MEM_callocN(sizeof(char)*me->totface, "linkflaguv"); + + for(med=me->medge, a=0; a < me->totedge; a++, med++) + if(med->flag & ME_SEAM) + BLI_edgehash_insert(seamhash, med->v1, med->v2, NULL); + + if (mode==0 || mode==1) { + /* only put face under cursor in array */ + mf= ((MFace*)me->mface) + index; + hash_add_face(ehash, mf); + linkflag[index]= 1; + } + else { + /* fill array by selection */ + mf= me->mface; + for(a=0; a<me->totface; a++, mf++) { + if(mf->flag & ME_HIDE); + else if(mf->flag & ME_FACE_SEL) { + hash_add_face(ehash, mf); + linkflag[a]= 1; + } + } + } + + while(doit) { + doit= 0; + + /* expand selection */ + mf= me->mface; + for(a=0; a<me->totface; a++, mf++) { + if(mf->flag & ME_HIDE) + continue; + + if(!linkflag[a]) { + mark= 0; + + if(!BLI_edgehash_haskey(seamhash, mf->v1, mf->v2)) + if(BLI_edgehash_haskey(ehash, mf->v1, mf->v2)) + mark= 1; + if(!BLI_edgehash_haskey(seamhash, mf->v2, mf->v3)) + if(BLI_edgehash_haskey(ehash, mf->v2, mf->v3)) + mark= 1; + if(mf->v4) { + if(!BLI_edgehash_haskey(seamhash, mf->v3, mf->v4)) + if(BLI_edgehash_haskey(ehash, mf->v3, mf->v4)) + mark= 1; + if(!BLI_edgehash_haskey(seamhash, mf->v4, mf->v1)) + if(BLI_edgehash_haskey(ehash, mf->v4, mf->v1)) + mark= 1; + } + else if(!BLI_edgehash_haskey(seamhash, mf->v3, mf->v1)) + if(BLI_edgehash_haskey(ehash, mf->v3, mf->v1)) + mark = 1; + + if(mark) { + linkflag[a]= 1; + hash_add_face(ehash, mf); + doit= 1; + } + } + } + + } + + BLI_edgehash_free(ehash, NULL); + BLI_edgehash_free(seamhash, NULL); + + if(mode==0 || mode==2) { + for(a=0, mf=me->mface; a<me->totface; a++, mf++) + if(linkflag[a]) + mf->flag |= ME_FACE_SEL; + else + mf->flag &= ~ME_FACE_SEL; + } + else if(mode==1) { + for(a=0, mf=me->mface; a<me->totface; a++, mf++) + if(linkflag[a] && (mf->flag & ME_FACE_SEL)) + break; + + if (a<me->totface) { + for(a=0, mf=me->mface; a<me->totface; a++, mf++) + if(linkflag[a]) + mf->flag &= ~ME_FACE_SEL; + } + else { + for(a=0, mf=me->mface; a<me->totface; a++, mf++) + if(linkflag[a]) + mf->flag |= ME_FACE_SEL; + } + } + + MEM_freeN(linkflag); + + // BIF_undo_push("Select linked UV face"); + // object_tface_flags_changed(OBACT, 0); +} + +void select_linked_tfaces(bContext *C, Object *ob, short mval[2], int mode) { - Object *ob; Mesh *me; - short mval[2]; unsigned int index=0; - ob = OBACT; me = get_mesh(ob); if(me==0 || me->totface==0) return; if (mode==0 || mode==1) { - if (!(ob->lay & v3d->lay)) - error("The active object is not in this layer"); - -// XXX getmouseco_areawin(mval); - if (!facesel_face_pick(v3d, me, mval, &index, 1)) return; + // XXX - Causes glitches, not sure why + /* + if (!facesel_face_pick(C, me, mval, &index, 1)) + return; + */ } -// XXX unwrapper.c select_linked_tfaces_with_seams(mode, me, index); + select_linked_tfaces_with_seams(mode, me, index); + + object_facesel_flush_dm(ob); } -void deselectall_tface(Scene *scene) +void deselectall_tface(Object *ob) { Mesh *me; MFace *mface; int a, sel; - - me= get_mesh(OBACT); + + me= get_mesh(ob); if(me==0) return; mface= me->mface; @@ -288,7 +410,7 @@ void deselectall_tface(Scene *scene) mface++; } - object_facesel_flush_dm(OBACT); + object_facesel_flush_dm(ob); // XXX notifier! object_tface_flags_changed(OBACT, 0); } @@ -693,73 +815,63 @@ int face_select(struct bContext *C, Object *ob, short mval[2], int extend) return 1; } -void face_borderselect(Scene *scene, ScrArea *sa, ARegion *ar) +void face_borderselect(struct bContext *C, Object *ob, rcti *rect, int select) { Mesh *me; MFace *mface; - rcti rect; struct ImBuf *ibuf; unsigned int *rt; - int a, sx, sy, index, val= 0; + int a, sx, sy, index; char *selar; - me= get_mesh(OBACT); + ViewContext vc; + view3d_set_viewcontext(C, &vc); + + me= get_mesh(ob); if(me==0) return; if(me->totface==0) return; - -// XXX val= get_border(&rect, 3); - - if(val) { - /* without this border select often fails */ -#if 0 /* XXX untested in 2.5 */ - if (v3d->flag & V3D_NEEDBACKBUFDRAW) { - check_backbuf(); - persp(PERSP_VIEW); - } -#endif - - selar= MEM_callocN(me->totface+1, "selar"); - - sx= (rect.xmax-rect.xmin+1); - sy= (rect.ymax-rect.ymin+1); - if(sx*sy<=0) return; - - ibuf = IMB_allocImBuf(sx,sy,32,IB_rect,0); - rt = ibuf->rect; - glReadPixels(rect.xmin+ar->winrct.xmin, rect.ymin+ar->winrct.ymin, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); - if(ENDIAN_ORDER==B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf); - - a= sx*sy; - while(a--) { - if(*rt) { - index= WM_framebuffer_to_index(*rt); - if(index<=me->totface) selar[index]= 1; - } - rt++; + + selar= MEM_callocN(me->totface+1, "selar"); + + sx= (rect->xmax-rect->xmin+1); + sy= (rect->ymax-rect->ymin+1); + if(sx*sy<=0) return; + + view3d_validate_backbuf(&vc); + + ibuf = IMB_allocImBuf(sx,sy,32,IB_rect,0); + rt = ibuf->rect; + glReadPixels(rect->xmin+vc.ar->winrct.xmin, rect->ymin+vc.ar->winrct.ymin, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); + if(ENDIAN_ORDER==B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf); + + a= sx*sy; + while(a--) { + if(*rt) { + index= WM_framebuffer_to_index(*rt); + if(index<=me->totface) selar[index]= 1; } - - mface= me->mface; - for(a=1; a<=me->totface; a++, mface++) { - if(selar[a]) { - if(mface->flag & ME_HIDE); - else { - if(val==LEFTMOUSE) mface->flag |= ME_FACE_SEL; - else mface->flag &= ~ME_FACE_SEL; - } + rt++; + } + + mface= me->mface; + for(a=1; a<=me->totface; a++, mface++) { + if(selar[a]) { + if(mface->flag & ME_HIDE); + else { + if(select) mface->flag |= ME_FACE_SEL; + else mface->flag &= ~ME_FACE_SEL; } } - - IMB_freeImBuf(ibuf); - MEM_freeN(selar); + } + + IMB_freeImBuf(ibuf); + MEM_freeN(selar); // XXX notifier! object_tface_flags_changed(OBACT, 0); - } #ifdef __APPLE__ glReadBuffer(GL_BACK); #endif - object_facesel_flush_dm(OBACT); + object_facesel_flush_dm(ob); } - - diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 92ef8ae8fd1..929f854242f 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -5254,6 +5254,5 @@ void PAINT_OT_texture_paint_radial_control(wmOperatorType *ot) int facemask_paint_poll(bContext *C) { - Object *obact = CTX_data_active_object(C); - return paint_facesel_test(obact); + return paint_facesel_test(CTX_data_active_object(C)); } diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h index d1ecc3e4dc0..b5748d7bc88 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.h +++ b/source/blender/editors/sculpt_paint/paint_intern.h @@ -94,6 +94,10 @@ void imapaint_pick_uv(struct Scene *scene, struct Object *ob, struct Mesh *mesh, void paint_sample_color(struct Scene *scene, struct ARegion *ar, int x, int y); void BRUSH_OT_curve_preset(struct wmOperatorType *ot); +void PAINT_OT_face_select_linked(struct wmOperatorType *ot); +void PAINT_OT_face_select_linked_pick(struct wmOperatorType *ot); +void PAINT_OT_face_deselect_all(struct wmOperatorType *ot); + int facemask_paint_poll(struct bContext *C); #endif /* ED_PAINT_INTERN_H */ diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c index 8184471c8d8..d8f13f679a5 100644 --- a/source/blender/editors/sculpt_paint/paint_ops.c +++ b/source/blender/editors/sculpt_paint/paint_ops.c @@ -133,6 +133,11 @@ void ED_operatortypes_paint(void) WM_operatortype_append(PAINT_OT_vertex_paint_toggle); WM_operatortype_append(PAINT_OT_vertex_paint); WM_operatortype_append(PAINT_OT_vertex_color_set); + + /* face-select */ + WM_operatortype_append(PAINT_OT_face_select_linked); + WM_operatortype_append(PAINT_OT_face_select_linked_pick); + WM_operatortype_append(PAINT_OT_face_deselect_all); } void ED_keymap_paint(wmKeyConfig *keyconf) @@ -184,5 +189,13 @@ void ED_keymap_paint(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "PAINT_OT_image_paint", LEFTMOUSE, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "PAINT_OT_sample_color", RIGHTMOUSE, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "PAINT_OT_clone_cursor_set", LEFTMOUSE, KM_PRESS, KM_CTRL, 0); -} + /* face-mask mode */ + keymap= WM_keymap_find(keyconf, "Face Mask", 0, 0); + keymap->poll= facemask_paint_poll; + + WM_keymap_add_item(keymap, "PAINT_OT_face_deselect_all", AKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "PAINT_OT_face_select_linked", LKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "PAINT_OT_face_select_linked_pick", LKEY, KM_PRESS, 0, 0); + +} diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index 13fbd2179b8..15104068350 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -26,6 +26,10 @@ #include "BIF_gl.h" #include "ED_view3d.h" +#include "ED_screen.h" + +#include "BLO_sys_types.h" +#include "ED_mesh.h" /* for face mask functions */ #include "WM_api.h" #include "WM_types.h" @@ -224,3 +228,67 @@ void BRUSH_OT_curve_preset(wmOperatorType *ot) RNA_def_enum(ot->srna, "shape", prop_shape_items, BRUSH_PRESET_SHARP, "Mode", ""); } + + +/* face-select ops */ +static int paint_select_linked_exec(bContext *C, wmOperator *op) +{ + select_linked_tfaces(C, CTX_data_active_object(C), NULL, 2); + ED_region_tag_redraw(CTX_wm_region(C)); + return OPERATOR_FINISHED; +} + +void PAINT_OT_face_select_linked(wmOperatorType *ot) +{ + ot->name= "Select Linked"; + ot->description= "Select linked faces."; + ot->idname= "PAINT_OT_face_select_linked"; + + ot->exec= paint_select_linked_exec; + ot->poll= facemask_paint_poll; + + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +static int paint_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + int mode= RNA_boolean_get(op->ptr, "extend") ? 1:0; + select_linked_tfaces(C, CTX_data_active_object(C), event->mval, mode); + ED_region_tag_redraw(CTX_wm_region(C)); + return OPERATOR_FINISHED; +} + +void PAINT_OT_face_select_linked_pick(wmOperatorType *ot) +{ + ot->name= "Select Linked Pick"; + ot->description= "Select linked faces."; + ot->idname= "PAINT_OT_face_select_linked_pick"; + + ot->invoke= paint_select_linked_pick_invoke; + ot->poll= facemask_paint_poll; + + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the existing selection"); +} + + +static int face_deselect_all_exec(bContext *C, wmOperator *op) +{ + deselectall_tface(CTX_data_active_object(C)); + ED_region_tag_redraw(CTX_wm_region(C)); + return OPERATOR_FINISHED; +} + + +void PAINT_OT_face_deselect_all(wmOperatorType *ot) +{ + ot->name= "Select Linked"; + ot->description= "Select linked faces under the mouse."; + ot->idname= "PAINT_OT_face_deselect_all"; + + ot->exec= face_deselect_all_exec; + ot->poll= facemask_paint_poll; + + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 86e9743d5bb..695d86bb51b 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -330,6 +330,9 @@ static void view3d_main_area_init(wmWindowManager *wm, ARegion *ar) keymap= WM_keymap_find(wm->defaultconf, "Weight Paint", 0, 0); WM_event_add_keymap_handler(&ar->handlers, keymap); + + keymap= WM_keymap_find(wm->defaultconf, "Face Mask", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); keymap= WM_keymap_find(wm->defaultconf, "Sculpt", 0, 0); WM_event_add_keymap_handler(&ar->handlers, keymap); diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index adb40a017ba..12b26e1d815 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -1392,7 +1392,7 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op) rect.ymax= RNA_int_get(op->ptr, "ymax"); if(obedit==NULL && (paint_facesel_test(OBACT))) { -// XXX face_borderselect(); + face_borderselect(C, obact, &rect, (val==LEFTMOUSE)); return OPERATOR_FINISHED; } else if(obedit==NULL && (obact && obact->mode & OB_MODE_PARTICLE_EDIT)) { |