diff options
Diffstat (limited to 'source/blender/windowmanager/intern/wm_operators.c')
-rw-r--r-- | source/blender/windowmanager/intern/wm_operators.c | 174 |
1 files changed, 130 insertions, 44 deletions
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 2daac07b956..012b1e21d9f 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -2303,6 +2303,43 @@ void WM_paint_cursor_end(wmWindowManager *wm, void *handle) * These are default callbacks for use in operators requiring gesture input */ +static void gesture_modal_state_to_operator(wmOperator *op, int modal_state) +{ + PropertyRNA *prop; + + switch (modal_state) { + case GESTURE_MODAL_SELECT: + case GESTURE_MODAL_DESELECT: + if ((prop = RNA_struct_find_property(op->ptr, "deselect"))) { + RNA_property_boolean_set(op->ptr, prop, (modal_state == GESTURE_MODAL_DESELECT)); + } + break; + case GESTURE_MODAL_IN: + case GESTURE_MODAL_OUT: + if ((prop = RNA_struct_find_property(op->ptr, "zoom_out"))) { + RNA_property_boolean_set(op->ptr, prop, (modal_state == GESTURE_MODAL_OUT)); + } + break; + } +} + +static int gesture_modal_state_from_operator(wmOperator *op) +{ + PropertyRNA *prop; + + if ((prop = RNA_struct_find_property(op->ptr, "deselect"))) { + if (RNA_property_is_set(op->ptr, prop)) { + return RNA_property_boolean_get(op->ptr, prop) ? GESTURE_MODAL_DESELECT : GESTURE_MODAL_SELECT; + } + } + if ((prop = RNA_struct_find_property(op->ptr, "zoom_out"))) { + if (RNA_property_is_set(op->ptr, prop)) { + return RNA_property_boolean_get(op->ptr, prop) ? GESTURE_MODAL_OUT : GESTURE_MODAL_IN; + } + } + return GESTURE_MODAL_NOP; +} + /* **************** Border gesture *************** */ /** @@ -2313,7 +2350,7 @@ void WM_paint_cursor_end(wmWindowManager *wm, void *handle) * It stores 4 values (xmin, xmax, ymin, ymax) and event it ended with (event_type) */ -static int border_apply_rect(wmOperator *op) +static bool gesture_border_apply_rect(wmOperator *op) { wmGesture *gesture = op->customdata; rcti *rect = gesture->customdata; @@ -2331,20 +2368,18 @@ static int border_apply_rect(wmOperator *op) return 1; } -static int border_apply(bContext *C, wmOperator *op, int gesture_mode) +static bool gesture_border_apply(bContext *C, wmOperator *op) { - PropertyRNA *prop; + wmGesture *gesture = op->customdata; int retval; - if (!border_apply_rect(op)) + if (!gesture_border_apply_rect(op)) { return 0; - - /* XXX weak; border should be configured for this without reading event types */ - if ((prop = RNA_struct_find_property(op->ptr, "gesture_mode"))) { - RNA_property_int_set(op->ptr, prop, gesture_mode); } + gesture_modal_state_to_operator(op, gesture->modal_state); + retval = op->type->exec(C, op); OPERATOR_RETVAL_CHECK(retval); @@ -2365,22 +2400,36 @@ static void wm_gesture_end(bContext *C, wmOperator *op) } } -int WM_border_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) +int WM_gesture_border_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (ISTWEAK(event->type)) + int modal_state = gesture_modal_state_from_operator(op); + + if (ISTWEAK(event->type) || (modal_state != GESTURE_MODAL_NOP)) { op->customdata = WM_gesture_new(C, event, WM_GESTURE_RECT); - else + } + else { op->customdata = WM_gesture_new(C, event, WM_GESTURE_CROSS_RECT); + } + + /* Starting with the mode starts immediately, like having 'wait_for_input' disabled (some tools use this). */ + if (modal_state == GESTURE_MODAL_NOP) { + wmGesture *gesture = op->customdata; + gesture->wait_for_input = true; + } + else { + wmGesture *gesture = op->customdata; + gesture->modal_state = modal_state; + } /* add modal handler */ WM_event_add_modal_handler(C, op); - + wm_gesture_tag_redraw(C); return OPERATOR_RUNNING_MODAL; } -int WM_border_select_modal(bContext *C, wmOperator *op, const wmEvent *event) +int WM_gesture_border_modal(bContext *C, wmOperator *op, const wmEvent *event) { wmGesture *gesture = op->customdata; rcti *rect = gesture->customdata; @@ -2397,7 +2446,7 @@ int WM_border_select_modal(bContext *C, wmOperator *op, const wmEvent *event) rect->xmax = event->x - sx; rect->ymax = event->y - sy; } - border_apply_rect(op); + gesture_border_apply_rect(op); wm_gesture_tag_redraw(C); } @@ -2413,7 +2462,10 @@ int WM_border_select_modal(bContext *C, wmOperator *op, const wmEvent *event) case GESTURE_MODAL_DESELECT: case GESTURE_MODAL_IN: case GESTURE_MODAL_OUT: - if (border_apply(C, op, event->val)) { + if (gesture->wait_for_input) { + gesture->modal_state = event->val; + } + if (gesture_border_apply(C, op)) { wm_gesture_end(C, op); return OPERATOR_FINISHED; } @@ -2439,7 +2491,7 @@ int WM_border_select_modal(bContext *C, wmOperator *op, const wmEvent *event) return OPERATOR_RUNNING_MODAL; } -void WM_border_select_cancel(bContext *C, wmOperator *op) +void WM_gesture_border_cancel(bContext *C, wmOperator *op) { wm_gesture_end(C, op); } @@ -2447,14 +2499,29 @@ void WM_border_select_cancel(bContext *C, wmOperator *op) /* **************** circle gesture *************** */ /* works now only for selection or modal paint stuff, calls exec while hold mouse, exit on release */ -#ifdef GESTURE_MEMORY -int circle_select_size = 25; /* XXX - need some operator memory thing! */ -#endif +static void gesture_circle_apply(bContext *C, wmOperator *op); int WM_gesture_circle_invoke(bContext *C, wmOperator *op, const wmEvent *event) { + int modal_state = gesture_modal_state_from_operator(op); + op->customdata = WM_gesture_new(C, event, WM_GESTURE_CIRCLE); + wmGesture *gesture = op->customdata; + rcti *rect = gesture->customdata; + /* Default or previously stored value. */ + rect->xmax = RNA_int_get(op->ptr, "radius"); + + /* Starting with the mode starts immediately, like having 'wait_for_input' disabled (some tools use this). */ + if (modal_state == GESTURE_MODAL_NOP) { + gesture->wait_for_input = true; + } + else { + gesture->is_active = true; + gesture->modal_state = modal_state; + gesture_circle_apply(C, op); + } + /* add modal handler */ WM_event_add_modal_handler(C, op); @@ -2467,23 +2534,23 @@ static void gesture_circle_apply(bContext *C, wmOperator *op) { wmGesture *gesture = op->customdata; rcti *rect = gesture->customdata; - - if (RNA_int_get(op->ptr, "gesture_mode") == GESTURE_MODAL_NOP) + + if (gesture->modal_state == GESTURE_MODAL_NOP) { return; + } /* 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); - + + gesture_modal_state_to_operator(op, gesture->modal_state); + if (op->type->exec) { int retval; retval = op->type->exec(C, op); OPERATOR_RETVAL_CHECK(retval); } -#ifdef GESTURE_MEMORY - circle_select_size = rect->xmax; -#endif } int WM_gesture_circle_modal(bContext *C, wmOperator *op, const wmEvent *event) @@ -2505,6 +2572,8 @@ int WM_gesture_circle_modal(bContext *C, wmOperator *op, const wmEvent *event) } } else if (event->type == EVT_MODAL_MAP) { + bool is_circle_size = false; + bool is_finished = false; float fac; switch (event->val) { @@ -2515,35 +2584,53 @@ int WM_gesture_circle_modal(bContext *C, wmOperator *op, const wmEvent *event) else rect->xmax += floor(fac); if (rect->xmax < 1) rect->xmax = 1; - wm_gesture_tag_redraw(C); + is_circle_size = true; break; case GESTURE_MODAL_CIRCLE_ADD: rect->xmax += 2 + rect->xmax / 10; - wm_gesture_tag_redraw(C); + is_circle_size = true; break; case GESTURE_MODAL_CIRCLE_SUB: rect->xmax -= 2 + rect->xmax / 10; if (rect->xmax < 1) rect->xmax = 1; - wm_gesture_tag_redraw(C); + is_circle_size = true; break; case GESTURE_MODAL_SELECT: case GESTURE_MODAL_DESELECT: case GESTURE_MODAL_NOP: - if (RNA_struct_find_property(op->ptr, "gesture_mode")) - RNA_int_set(op->ptr, "gesture_mode", event->val); - - if (event->val != GESTURE_MODAL_NOP) { + { + if (gesture->wait_for_input) { + gesture->modal_state = event->val; + } + if (event->val == GESTURE_MODAL_NOP) { + /* Single action, click-drag & release to exit. */ + if (gesture->wait_for_input == false) { + is_finished = true; + } + } + else { /* apply first click */ gesture_circle_apply(C, op); gesture->is_active = true; wm_gesture_tag_redraw(C); } break; - + } case GESTURE_MODAL_CANCEL: case GESTURE_MODAL_CONFIRM: - wm_gesture_end(C, op); - return OPERATOR_FINISHED; /* use finish or we don't get an undo */ + is_finished = true; + } + + if (is_finished) { + wm_gesture_end(C, op); + return OPERATOR_FINISHED; /* use finish or we don't get an undo */ + } + + if (is_circle_size) { + wm_gesture_tag_redraw(C); + + /* So next use remembers last seen size, even if we didn't apply it. */ + RNA_int_set(op->ptr, "radius", rect->xmax); } } #ifdef WITH_INPUT_NDOF @@ -2575,12 +2662,10 @@ void WM_OT_circle_gesture(wmOperatorType *ot) 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); + + /* properties */ + WM_operator_properties_gesture_circle(ot); } #endif @@ -4353,14 +4438,15 @@ static void gesture_circle_modal_keymap(wmKeyConfig *keyconf) WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, 0, 0, GESTURE_MODAL_SELECT); + /* Note: use 'KM_ANY' for release, so the circle exits on any mouse release, + * this is needed when circle select is activated as a tool. */ + /* left mouse shift for deselect too */ WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_SHIFT, 0, GESTURE_MODAL_DESELECT); - WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_SHIFT, 0, GESTURE_MODAL_NOP); + WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, GESTURE_MODAL_NOP); WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_PRESS, 0, 0, GESTURE_MODAL_DESELECT); // default 2.4x - WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, 0, 0, GESTURE_MODAL_NOP); // default 2.4x - - WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, 0, 0, GESTURE_MODAL_NOP); + WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, GESTURE_MODAL_NOP); // default 2.4x WM_modalkeymap_add_item(keymap, WHEELUPMOUSE, KM_PRESS, 0, 0, GESTURE_MODAL_CIRCLE_SUB); WM_modalkeymap_add_item(keymap, PADMINUS, KM_PRESS, 0, 0, GESTURE_MODAL_CIRCLE_SUB); |