diff options
author | Campbell Barton <ideasman42@gmail.com> | 2017-10-16 14:28:24 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2017-10-16 14:28:24 +0300 |
commit | a2758152e2dccb3b016e13a3de2d9e58587866ab (patch) | |
tree | d872a7ae82e682012758c12eb5d8c8e63828c00d /source/blender/windowmanager/intern | |
parent | 14af3e485f1207e8f4ddb6991b22e1ba2f937c45 (diff) | |
parent | 870b4b673511094cf0beaeaf07305407ccdda47a (diff) |
Merge branch 'master' into blender2.8
Diffstat (limited to 'source/blender/windowmanager/intern')
-rw-r--r-- | source/blender/windowmanager/intern/wm_event_system.c | 21 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_gesture.c | 7 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_operator_props.c | 103 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_operators.c | 174 |
4 files changed, 233 insertions, 72 deletions
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index fe79798c3b7..e842db64015 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -773,12 +773,16 @@ static bool wm_operator_register_check(wmWindowManager *wm, wmOperatorType *ot) return wm && (wm->op_undo_depth == 0) && (ot->flag & (OPTYPE_REGISTER | OPTYPE_UNDO)); } -static void wm_operator_finished(bContext *C, wmOperator *op, const bool repeat) +static void wm_operator_finished(bContext *C, wmOperator *op, const bool repeat, const bool store) { wmWindowManager *wm = CTX_wm_manager(C); op->customdata = NULL; + if (store) { + WM_operator_last_properties_store(op); + } + /* we don't want to do undo pushes for operators that are being * called from operators that already do an undo push. usually * this will happen for python operators that call C operators */ @@ -841,12 +845,7 @@ static int wm_operator_exec(bContext *C, wmOperator *op, const bool repeat, cons wm_operator_reports(C, op, retval, false); if (retval & OPERATOR_FINISHED) { - if (store) { - if (wm->op_undo_depth == 0) { /* not called by py script */ - WM_operator_last_properties_store(op); - } - } - wm_operator_finished(C, op, repeat); + wm_operator_finished(C, op, repeat, store && wm->op_undo_depth == 0); } else if (repeat == 0) { /* warning: modal from exec is bad practice, but avoid crashing. */ @@ -1202,10 +1201,8 @@ static int wm_operator_invoke( /* do nothing, wm_operator_exec() has been called somewhere */ } else if (retval & OPERATOR_FINISHED) { - if (!is_nested_call) { /* not called by py script */ - WM_operator_last_properties_store(op); - } - wm_operator_finished(C, op, 0); + const bool store = !is_nested_call; + wm_operator_finished(C, op, false, store); } else if (retval & OPERATOR_RUNNING_MODAL) { /* take ownership of reports (in case python provided own) */ @@ -1811,7 +1808,7 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand /* important to run 'wm_operator_finished' before NULLing the context members */ if (retval & OPERATOR_FINISHED) { - wm_operator_finished(C, op, 0); + wm_operator_finished(C, op, false, true); handler->op = NULL; } else if (retval & (OPERATOR_CANCELLED | OPERATOR_FINISHED)) { diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c index 7f1ca929fd6..fa5fd38b7b2 100644 --- a/source/blender/windowmanager/intern/wm_gesture.c +++ b/source/blender/windowmanager/intern/wm_gesture.c @@ -72,6 +72,7 @@ wmGesture *WM_gesture_new(bContext *C, const wmEvent *event, int type) gesture->event_type = event->type; gesture->swinid = ar->swinid; /* means only in area-region context! */ gesture->userdata_free = true; /* Free if userdata is set. */ + gesture->modal_state = GESTURE_MODAL_NOP; wm_subwindow_origin_get(window, gesture->swinid, &sx, &sy); @@ -84,11 +85,7 @@ wmGesture *WM_gesture_new(bContext *C, const wmEvent *event, int type) rect->xmin = event->x - sx; rect->ymin = event->y - sy; if (type == WM_GESTURE_CIRCLE) { -#ifdef GESTURE_MEMORY - rect->xmax = circle_select_size; -#else - rect->xmax = 25; // XXX temp -#endif + /* caller is responsible for initializing 'xmax' to radius. */ } else { rect->xmax = event->x - sx; diff --git a/source/blender/windowmanager/intern/wm_operator_props.c b/source/blender/windowmanager/intern/wm_operator_props.c index 18836f34c99..4873a6bbf81 100644 --- a/source/blender/windowmanager/intern/wm_operator_props.c +++ b/source/blender/windowmanager/intern/wm_operator_props.c @@ -224,30 +224,69 @@ void WM_operator_properties_border_to_rctf(struct wmOperator *op, rctf *rect) BLI_rctf_rcti_copy(rect, &rect_i); } -void WM_operator_properties_gesture_border(wmOperatorType *ot, bool extend) +/** + * Use with #WM_gesture_border_invoke + */ +void WM_operator_properties_gesture_border_ex(wmOperatorType *ot, bool deselect, bool extend) { - RNA_def_int(ot->srna, "gesture_mode", 0, INT_MIN, INT_MAX, "Gesture Mode", "", INT_MIN, INT_MAX); - WM_operator_properties_border(ot); + if (deselect) { + RNA_def_boolean(ot->srna, "deselect", false, "Deselect", "Deselect rather than select items"); + } if (extend) { RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend selection instead of deselecting everything first"); } } -void WM_operator_properties_mouse_select(wmOperatorType *ot) +void WM_operator_properties_gesture_border_select(wmOperatorType *ot) +{ + WM_operator_properties_gesture_border_ex(ot, true, true); +} +void WM_operator_properties_gesture_border(wmOperatorType *ot) +{ + WM_operator_properties_gesture_border_ex(ot, false, false); +} + +void WM_operator_properties_gesture_border_zoom(wmOperatorType *ot) { + WM_operator_properties_border(ot); + PropertyRNA *prop; + prop = RNA_def_boolean(ot->srna, "zoom_out", false, "Zoom Out", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); +} - prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", - "Extend selection instead of deselecting everything first"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "deselect", false, "Deselect", "Remove from selection"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "toggle", false, "Toggle Selection", "Toggle the selection"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); +/** + * Use with #WM_gesture_lasso_invoke + */ +void WM_operator_properties_gesture_lasso_ex(wmOperatorType *ot, bool deselect, bool extend) +{ + PropertyRNA *prop; + prop = RNA_def_collection_runtime(ot->srna, "path", &RNA_OperatorMousePath, "Path", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + + if (deselect) { + RNA_def_boolean(ot->srna, "deselect", false, "Deselect", "Deselect rather than select items"); + } + if (extend) { + RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend selection instead of deselecting everything first"); + } } +void WM_operator_properties_gesture_lasso(wmOperatorType *ot) +{ + WM_operator_properties_gesture_lasso_ex(ot, false, false); +} + +void WM_operator_properties_gesture_lasso_select(wmOperatorType *ot) +{ + WM_operator_properties_gesture_lasso_ex(ot, true, true); +} + +/** + * Use with #WM_gesture_straightline_invoke + */ void WM_operator_properties_gesture_straightline(wmOperatorType *ot, int cursor) { PropertyRNA *prop; @@ -269,6 +308,48 @@ void WM_operator_properties_gesture_straightline(wmOperatorType *ot, int cursor) } /** + * Use with #WM_gesture_circle_invoke + */ +void WM_operator_properties_gesture_circle_ex(wmOperatorType *ot, bool deselect) +{ + PropertyRNA *prop; + const int radius_default = 25; + + prop = RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + RNA_def_int(ot->srna, "radius", radius_default, 1, INT_MAX, "Radius", "", 1, INT_MAX); + + if (deselect) { + RNA_def_boolean(ot->srna, "deselect", false, "Deselect", "Deselect rather than select items"); + } +} + +void WM_operator_properties_gesture_circle(wmOperatorType *ot) +{ + WM_operator_properties_gesture_circle_ex(ot, false); +} + +void WM_operator_properties_gesture_circle_select(wmOperatorType *ot) +{ + WM_operator_properties_gesture_circle_ex(ot, true); +} + +void WM_operator_properties_mouse_select(wmOperatorType *ot) +{ + PropertyRNA *prop; + + prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", + "Extend selection instead of deselecting everything first"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "deselect", false, "Deselect", "Remove from selection"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "toggle", false, "Toggle Selection", "Toggle the selection"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); +} + +/** * \param nth_can_disable: Enable if we want to be able to select no interval at all. */ void WM_operator_properties_checker_interval(wmOperatorType *ot, bool nth_can_disable) 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); |