From eb8e220f26183fe92945247a45aabe9447871285 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Sun, 21 Dec 2008 16:24:19 +0000 Subject: 2.5 - Added default Circle 'gesture' operator callbacks. As test, added in view3d window as Ckey, paint over object centers. - Fixed notifier for gesture, to only cause redraws in own region. --- source/blender/editors/screen/area.c | 5 +- .../blender/editors/space_view3d/view3d_intern.h | 1 + source/blender/editors/space_view3d/view3d_ops.c | 3 +- .../blender/editors/space_view3d/view3d_select.c | 42 ++++++++ source/blender/windowmanager/WM_api.h | 4 +- source/blender/windowmanager/WM_types.h | 1 + source/blender/windowmanager/intern/wm_gesture.c | 32 +++++- source/blender/windowmanager/intern/wm_init_exit.c | 1 + source/blender/windowmanager/intern/wm_operators.c | 120 +++++++++++++++++++-- 9 files changed, 197 insertions(+), 12 deletions(-) (limited to 'source') diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 194000a8362..fcee8726d9d 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -106,10 +106,13 @@ void ED_region_do_listen(ARegion *ar, wmNotifier *note) /* generic notes first */ switch(note->type) { case WM_NOTE_WINDOW_REDRAW: - case WM_NOTE_GESTURE_REDRAW: case WM_NOTE_SCREEN_CHANGED: ED_region_tag_redraw(ar); break; + case WM_NOTE_GESTURE_REDRAW: + if(note->swinid==ar->swinid) + ED_region_tag_redraw(ar); + break; default: if(ar->type->listener) ar->type->listener(ar, note); diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 2f3541e0d85..aacad634d2b 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -110,6 +110,7 @@ void view3d_update_depths(ARegion *ar, View3D *v3d); /* view3d_select.c */ void ED_VIEW3D_OT_select(struct wmOperatorType *ot); void ED_VIEW3D_OT_borderselect(struct wmOperatorType *ot); +void ED_VIEW3D_OT_circle_select(struct wmOperatorType *ot); /* view3d_view.c */ void view3d_operator_needs_opengl(const struct bContext *C); diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index 92564d8b20b..3ac05ed4bfc 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -69,7 +69,7 @@ void view3d_operatortypes(void) WM_operatortype_append(ED_VIEW3D_OT_select); WM_operatortype_append(ED_VIEW3D_OT_borderselect); WM_operatortype_append(ED_VIEW3D_OT_clipping); - + WM_operatortype_append(ED_VIEW3D_OT_circle_select); } void view3d_keymap(wmWindowManager *wm) @@ -92,6 +92,7 @@ void view3d_keymap(wmWindowManager *wm) WM_keymap_add_item(keymap, "ED_VIEW3D_OT_select", SELECTMOUSE, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "ED_VIEW3D_OT_borderselect", BKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "ED_VIEW3D_OT_clipping", BKEY, KM_PRESS, KM_ALT, 0); + WM_keymap_add_item(keymap, "ED_VIEW3D_OT_circle_select", CKEY, KM_PRESS, 0, 0); } diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 029211919e5..0d9a92c86c3 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -1859,3 +1859,45 @@ void obedit_selectionCB(Scene *scene, ARegion *ar, View3D *v3d, short selecting, // force_draw(0); } +static int view3d_circle_select(bContext *C, wmOperator *op) +{ + ScrArea *sa= CTX_wm_area(C); + ARegion *ar= CTX_wm_region(C); + View3D *v3d= sa->spacedata.first; + Base *base; + + int x= RNA_int_get(op->ptr, "x"); + int y= RNA_int_get(op->ptr, "y"); + int radius= RNA_int_get(op->ptr, "radius"); + + for(base= FIRSTBASE; base; base= base->next) { + if(base->lay & v3d->lay) { + project_short(ar, v3d, base->object->obmat[3], &base->sx); + if(base->sx!=IS_CLIPPED) { + int dx= base->sx-x; + int dy= base->sy-y; + if( dx*dx + dy*dy < radius*radius) + + select_base_v3d(base, BA_SELECT); + base->object->flag= base->flag; + } + } + } + return 0; +} + +void ED_VIEW3D_OT_circle_select(wmOperatorType *ot) +{ + ot->name= "Circle Select"; + ot->idname= "ED_VIEW3D_OT_circle_select"; + + ot->invoke= WM_gesture_circle_invoke; + ot->modal= WM_gesture_circle_modal; + ot->exec= view3d_circle_select; + ot->poll= WM_operator_winactive; + + RNA_def_property(ot->srna, "x", PROP_INT, PROP_NONE); + RNA_def_property(ot->srna, "y", PROP_INT, PROP_NONE); + RNA_def_property(ot->srna, "radius", PROP_INT, PROP_NONE); + +} diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index b1209af9afe..cca9794f79e 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -119,9 +119,11 @@ void WM_operatortype_append (void (*opfunc)(wmOperatorType*)); int WM_operator_call (struct bContext *C, const char *opstring, int context, struct IDProperty *properties); - /* default operator callbacks for border/lasso */ + /* default operator callbacks for border/circle/lasso */ int WM_border_select_invoke (struct bContext *C, wmOperator *op, struct wmEvent *event); int WM_border_select_modal (struct bContext *C, wmOperator *op, struct wmEvent *event); +int WM_gesture_circle_invoke(struct bContext *C, wmOperator *op, struct wmEvent *event); +int WM_gesture_circle_modal(struct bContext *C, wmOperator *op, struct wmEvent *event); /* default operator for arearegions, generates event */ void WM_OT_tweak_gesture(wmOperatorType *ot); diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index b85a83931bf..bccbcc178ba 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -146,6 +146,7 @@ typedef struct wmGesture { void *customdata; /* customdata for border is a recti */ + /* customdata for circle is recti, (xmin, ymin) is center, xmax radius */ } wmGesture; diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c index c5953310783..437a4494a2e 100644 --- a/source/blender/windowmanager/intern/wm_gesture.c +++ b/source/blender/windowmanager/intern/wm_gesture.c @@ -66,14 +66,18 @@ wmGesture *WM_gesture_new(bContext *C, wmEvent *event, int type) wm_subwindow_getorigin(window, gesture->swinid, &sx, &sy); - if( ELEM3(type, WM_GESTURE_RECT, WM_GESTURE_CROSS_RECT, WM_GESTURE_TWEAK)) { + if( ELEM4(type, WM_GESTURE_RECT, WM_GESTURE_CROSS_RECT, WM_GESTURE_TWEAK, WM_GESTURE_CIRCLE)) { rcti *rect= MEM_callocN(sizeof(rcti), "gesture rect new"); gesture->customdata= rect; rect->xmin= event->x - sx; rect->ymin= event->y - sy; - rect->xmax= event->x - sx; - rect->ymax= event->y - sy; + if(type==WM_GESTURE_CIRCLE) + rect->xmax= 25; // XXX temp + else { + rect->xmax= event->x - sx; + rect->ymax= event->y - sy; + } } return gesture; @@ -162,6 +166,26 @@ static void wm_gesture_draw_line(wmWindow *win, wmGesture *gt) } +static void wm_gesture_draw_circle(wmWindow *win, wmGesture *gt) +{ + rcti *rect= (rcti *)gt->customdata; + + glTranslatef((float)rect->xmin, (float)rect->ymin, 0.0f); + + glEnable(GL_LINE_STIPPLE); + glColor3ub(0, 0, 0); + glLineStipple(1, 0xAAAA); + glutil_draw_lined_arc(0.0, M_PI*2.0, rect->xmax, 40); + glColor3ub(255, 255, 255); + glLineStipple(1, 0x5555); + glutil_draw_lined_arc(0.0, M_PI*2.0, rect->xmax, 40); + + glDisable(GL_LINE_STIPPLE); + glTranslatef((float)-rect->xmin, (float)-rect->ymin, 0.0f); + +} + + static void wm_gesture_draw_cross(wmWindow *win, wmGesture *gt) { rcti *rect= (rcti *)gt->customdata; @@ -192,6 +216,8 @@ void wm_gesture_draw(wmWindow *win) wm_gesture_draw_rect(win, gt); else if(gt->type==WM_GESTURE_TWEAK) wm_gesture_draw_line(win, gt); + else if(gt->type==WM_GESTURE_CIRCLE) + wm_gesture_draw_circle(win, gt); else if(gt->type==WM_GESTURE_CROSS_RECT) { if(gt->mode==1) wm_gesture_draw_rect(win, gt); diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 5b76efe1239..5e61900ddc7 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -173,6 +173,7 @@ void WM_exit(bContext *C) /* first wrap up running stuff, we assume only the active WM is running */ /* modal handlers are on window level freed, others too? */ + /* note; same code copied in wm_files.c */ if(C && CTX_wm_manager(C)) { for(win= CTX_wm_manager(C)->windows.first; win; win= win->next) { diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 3158ea0759c..56909b425d2 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -249,7 +249,7 @@ static void WM_OT_exit_blender(wmOperatorType *ot) It stores 4 values (xmin, xmax, ymin, ymax) and event it ended with (event_type) */ -static void border_select_apply(bContext *C, wmOperator *op, int event_type) +static void border_apply(bContext *C, wmOperator *op, int event_type) { wmGesture *gesture= op->customdata; rcti *rect= gesture->customdata; @@ -264,13 +264,13 @@ static void border_select_apply(bContext *C, wmOperator *op, int event_type) RNA_int_set(op->ptr, "ymin", rect->ymin); RNA_int_set(op->ptr, "xmax", rect->xmax); RNA_int_set(op->ptr, "ymax", rect->ymax); - if( RNA_property_is_set(op->ptr, "event_type")) + if( RNA_struct_find_property(op->ptr, "event_type") ) RNA_int_set(op->ptr, "event_type", event_type); op->type->exec(C, op); } -static void border_select_end(bContext *C, wmOperator *op) +static void border_end(bContext *C, wmOperator *op) { wmGesture *gesture= op->customdata; @@ -327,18 +327,125 @@ int WM_border_select_modal(bContext *C, wmOperator *op, wmEvent *event) } } else { - border_select_apply(C, op, event->type); - border_select_end(C, op); + border_apply(C, op, event->type); + border_end(C, op); return OPERATOR_FINISHED; } break; case ESCKEY: - border_select_end(C, op); + border_end(C, op); return OPERATOR_CANCELLED; } return OPERATOR_RUNNING_MODAL; } +/* **************** circle gesture *************** */ +/* works now only for selection or modal paint stuff, calls exec while hold mouse */ + +int WM_gesture_circle_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + op->customdata= WM_gesture_new(C, event, WM_GESTURE_CIRCLE); + + /* add modal handler */ + WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + + WM_event_add_notifier(C, WM_NOTE_GESTURE_REDRAW, 0, NULL); + + return OPERATOR_RUNNING_MODAL; +} + +static void gesture_circle_end(bContext *C, wmOperator *op) +{ + wmGesture *gesture= op->customdata; + + WM_gesture_end(C, gesture); /* frees gesture itself, and unregisters from window */ + op->customdata= NULL; + + ED_area_tag_redraw(CTX_wm_area(C)); +} + +static void gesture_circle_apply(bContext *C, wmOperator *op, int event_type) +{ + wmGesture *gesture= op->customdata; + rcti *rect= gesture->customdata; + + /* operator arguments and storage. */ + RNA_int_set(op->ptr, "x", rect->xmin); + RNA_int_set(op->ptr, "y", rect->ymin); + RNA_int_set(op->ptr, "radius", rect->xmax); + if( RNA_struct_find_property(op->ptr, "event_type") ) + RNA_int_set(op->ptr, "event_type", event_type); + + if(op->type->exec) + op->type->exec(C, op); +} + +int WM_gesture_circle_modal(bContext *C, wmOperator *op, wmEvent *event) +{ + wmGesture *gesture= op->customdata; + rcti *rect= gesture->customdata; + int sx, sy; + + switch(event->type) { + case MOUSEMOVE: + + wm_subwindow_getorigin(CTX_wm_window(C), gesture->swinid, &sx, &sy); + + rect->xmin= event->x - sx; + rect->ymin= event->y - sy; + + WM_event_add_notifier(C, WM_NOTE_GESTURE_REDRAW, 0, NULL); + + if(gesture->mode) + gesture_circle_apply(C, op, event->type); + + break; + case WHEELUPMOUSE: + rect->xmax += 2 + rect->xmax/10; + WM_event_add_notifier(C, WM_NOTE_GESTURE_REDRAW, 0, NULL); + break; + case WHEELDOWNMOUSE: + rect->xmax -= 2 + rect->xmax/10; + if(rect->xmax < 1) rect->xmax= 1; + WM_event_add_notifier(C, WM_NOTE_GESTURE_REDRAW, 0, NULL); + break; + case LEFTMOUSE: + case MIDDLEMOUSE: + case RIGHTMOUSE: + if(event->val==0) { /* key release */ + gesture_circle_end(C, op); + return OPERATOR_FINISHED; + } + else + gesture->mode= 1; + + break; + case ESCKEY: + gesture_circle_end(C, op); + return OPERATOR_CANCELLED; + } + return OPERATOR_RUNNING_MODAL; +} + +#if 0 +/* template to copy from */ +void WM_OT_circle_gesture(wmOperatorType *ot) +{ + ot->name= "Circle Gesture"; + ot->idname= "WM_OT_circle_gesture"; + + ot->invoke= WM_gesture_circle_invoke; + ot->modal= WM_gesture_circle_modal; + + ot->poll= WM_operator_winactive; + + RNA_def_property(ot->srna, "x", PROP_INT, PROP_NONE); + RNA_def_property(ot->srna, "y", PROP_INT, PROP_NONE); + RNA_def_property(ot->srna, "radius", PROP_INT, PROP_NONE); + +} +#endif + /* **************** Tweak gesture *************** */ static int tweak_gesture_invoke(bContext *C, wmOperator *op, wmEvent *event) @@ -456,5 +563,6 @@ void wm_window_keymap(wmWindowManager *wm) WM_keymap_verify_item(keymap, "WM_OT_open_recentfile", OKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_verify_item(keymap, "WM_OT_window_fullscreen_toggle", FKEY, KM_PRESS, 0, 0); WM_keymap_verify_item(keymap, "WM_OT_exit_blender", QKEY, KM_PRESS, KM_CTRL, 0); + } -- cgit v1.2.3