From 8bda35d2f49879ced26e9069bce14ebf368761b3 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 16 Oct 2017 15:32:09 +1100 Subject: WM: remove hard-coded circle radius memory Replace with operator type 'last_properties'. Also use generic function for circle gesture properties. --- source/blender/windowmanager/WM_api.h | 3 +- source/blender/windowmanager/intern/wm_gesture.c | 6 +-- .../windowmanager/intern/wm_operator_props.c | 49 ++++++++++++++++------ source/blender/windowmanager/intern/wm_operators.c | 46 ++++++++++++-------- source/blender/windowmanager/wm.h | 8 ---- 5 files changed, 67 insertions(+), 45 deletions(-) (limited to 'source/blender/windowmanager') diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 7c1c388bcba..d91c4a4efe0 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -309,8 +309,9 @@ void WM_operator_properties_border(struct wmOperatorType *ot); void WM_operator_properties_border_to_rcti(struct wmOperator *op, struct rcti *rect); void WM_operator_properties_border_to_rctf(struct wmOperator *op, rctf *rect); void WM_operator_properties_gesture_border(struct wmOperatorType *ot, bool extend); -void WM_operator_properties_mouse_select(struct wmOperatorType *ot); void WM_operator_properties_gesture_straightline(struct wmOperatorType *ot, int cursor); +void WM_operator_properties_gesture_circle(struct wmOperatorType *ot); +void WM_operator_properties_mouse_select(struct wmOperatorType *ot); void WM_operator_properties_select_all(struct wmOperatorType *ot); void WM_operator_properties_select_action(struct wmOperatorType *ot, int default_action); void WM_operator_properties_select_action_simple(struct wmOperatorType *ot, int default_action); diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c index f66efa72908..11f39dc934c 100644 --- a/source/blender/windowmanager/intern/wm_gesture.c +++ b/source/blender/windowmanager/intern/wm_gesture.c @@ -84,11 +84,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..2a44b4997a2 100644 --- a/source/blender/windowmanager/intern/wm_operator_props.c +++ b/source/blender/windowmanager/intern/wm_operator_props.c @@ -224,6 +224,9 @@ void WM_operator_properties_border_to_rctf(struct wmOperator *op, rctf *rect) BLI_rctf_rcti_copy(rect, &rect_i); } +/** + * Use with #WM_border_select_invoke + */ void WM_operator_properties_gesture_border(wmOperatorType *ot, bool extend) { RNA_def_int(ot->srna, "gesture_mode", 0, INT_MIN, INT_MAX, "Gesture Mode", "", INT_MIN, INT_MAX); @@ -235,19 +238,9 @@ void WM_operator_properties_gesture_border(wmOperatorType *ot, bool extend) } } -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); -} - +/** + * Use with #WM_gesture_straightline_invoke + */ void WM_operator_properties_gesture_straightline(wmOperatorType *ot, int cursor) { PropertyRNA *prop; @@ -268,6 +261,36 @@ void WM_operator_properties_gesture_straightline(wmOperatorType *ot, int cursor) } } +/** + * Use with #WM_gesture_circle_invoke + */ +void WM_operator_properties_gesture_circle(wmOperatorType *ot) +{ + 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); + prop = RNA_def_int(ot->srna, "gesture_mode", 0, INT_MIN, INT_MAX, "Gesture Mode", "", INT_MIN, INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); +} + +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. */ diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 6fdc0a0a8c0..e4776ea7b29 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -2394,14 +2394,15 @@ 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 - int WM_gesture_circle_invoke(bContext *C, wmOperator *op, const wmEvent *event) { 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"); + /* add modal handler */ WM_event_add_modal_handler(C, op); @@ -2428,9 +2429,6 @@ static void gesture_circle_apply(bContext *C, wmOperator *op) 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) @@ -2452,6 +2450,7 @@ int WM_gesture_circle_modal(bContext *C, wmOperator *op, const wmEvent *event) } } else if (event->type == EVT_MODAL_MAP) { + bool is_circle_size = false; float fac; switch (event->val) { @@ -2462,22 +2461,25 @@ 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); + { + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "gesture_mode"); + if (prop != NULL) { + RNA_property_int_set(op->ptr, prop, event->val); + } if (event->val != GESTURE_MODAL_NOP) { /* apply first click */ @@ -2486,12 +2488,22 @@ int WM_gesture_circle_modal(bContext *C, wmOperator *op, const wmEvent *event) wm_gesture_tag_redraw(C); } break; - + } case GESTURE_MODAL_CANCEL: case GESTURE_MODAL_CONFIRM: + /* Normally we wouldn't store last-properties on cancel, + * this is an exception since the circle tool is modal. */ + WM_operator_last_properties_store(op); 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 else if (event->type == NDOF_MOTION) { @@ -2522,12 +2534,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 diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h index cb88ca3a474..c1cab8c8ff8 100644 --- a/source/blender/windowmanager/wm.h +++ b/source/blender/windowmanager/wm.h @@ -88,12 +88,4 @@ void wm_stereo3d_set_cancel(bContext *C, wmOperator *op); void wm_open_init_load_ui(wmOperator *op, bool use_prefs); void wm_open_init_use_scripts(wmOperator *op, bool use_prefs); -/* hack to store circle select size - campbell, must replace with nice operator memory */ -#define GESTURE_MEMORY - -#ifdef GESTURE_MEMORY -extern int circle_select_size; -#endif - #endif /* __WM_H__ */ - -- cgit v1.2.3 From 946a4fe85a1717001230ab5f256cf5cf10f045cb Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 16 Oct 2017 16:11:04 +1100 Subject: WM: Don't save mouse-paths to operator history In preparation for modal operators storing their properties, no need to keep mouse-paths around. Also use generic function for lasso properties. --- source/blender/windowmanager/WM_api.h | 2 ++ .../windowmanager/intern/wm_operator_props.c | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+) (limited to 'source/blender/windowmanager') diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index d91c4a4efe0..40722736d58 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -309,6 +309,8 @@ void WM_operator_properties_border(struct wmOperatorType *ot); void WM_operator_properties_border_to_rcti(struct wmOperator *op, struct rcti *rect); void WM_operator_properties_border_to_rctf(struct wmOperator *op, rctf *rect); void WM_operator_properties_gesture_border(struct wmOperatorType *ot, bool extend); +void WM_operator_properties_gesture_lasso_ex(struct wmOperatorType *ot, bool deselect, bool extend); +void WM_operator_properties_gesture_lasso(struct wmOperatorType *ot); void WM_operator_properties_gesture_straightline(struct wmOperatorType *ot, int cursor); void WM_operator_properties_gesture_circle(struct wmOperatorType *ot); void WM_operator_properties_mouse_select(struct wmOperatorType *ot); diff --git a/source/blender/windowmanager/intern/wm_operator_props.c b/source/blender/windowmanager/intern/wm_operator_props.c index 2a44b4997a2..569cd43a524 100644 --- a/source/blender/windowmanager/intern/wm_operator_props.c +++ b/source/blender/windowmanager/intern/wm_operator_props.c @@ -238,6 +238,28 @@ void WM_operator_properties_gesture_border(wmOperatorType *ot, bool extend) } } +/** + * 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, true, true); +} + /** * Use with #WM_gesture_straightline_invoke */ -- cgit v1.2.3 From 83b60dac57a1aa432c8f7c165603ef327c6911d6 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 16 Oct 2017 16:35:22 +1100 Subject: WM: store modal operator last-properties Avoids modal operators needing to explicitly store them. --- .../blender/windowmanager/intern/wm_event_system.c | 21 +++++++++------------ source/blender/windowmanager/intern/wm_operators.c | 3 --- 2 files changed, 9 insertions(+), 15 deletions(-) (limited to 'source/blender/windowmanager') diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index a6777d40398..6ebe1671afc 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -744,12 +744,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 */ @@ -812,12 +816,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. */ @@ -1173,10 +1172,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) */ @@ -1752,7 +1749,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_operators.c b/source/blender/windowmanager/intern/wm_operators.c index e4776ea7b29..307c8b24c1e 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -2491,9 +2491,6 @@ int WM_gesture_circle_modal(bContext *C, wmOperator *op, const wmEvent *event) } case GESTURE_MODAL_CANCEL: case GESTURE_MODAL_CONFIRM: - /* Normally we wouldn't store last-properties on cancel, - * this is an exception since the circle tool is modal. */ - WM_operator_last_properties_store(op); wm_gesture_end(C, op); return OPERATOR_FINISHED; /* use finish or we don't get an undo */ } -- cgit v1.2.3 From 8550c2b92251815a39f95a9128f1fbc51f204a07 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 16 Oct 2017 17:01:28 +1100 Subject: Cleanup: modal operator border callback names Use same convention as all others. Remove 'select' since these are used for zoom as well. --- source/blender/windowmanager/WM_api.h | 6 +++--- source/blender/windowmanager/intern/wm_operator_props.c | 2 +- source/blender/windowmanager/intern/wm_operators.c | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'source/blender/windowmanager') diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 40722736d58..aa52e7d2248 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -374,9 +374,9 @@ void WM_menutype_freelink(struct MenuType *mt); void WM_menutype_free(void); /* default operator callbacks for border/circle/lasso */ -int WM_border_select_invoke (struct bContext *C, struct wmOperator *op, const struct wmEvent *event); -int WM_border_select_modal (struct bContext *C, struct wmOperator *op, const struct wmEvent *event); -void WM_border_select_cancel(struct bContext *C, struct wmOperator *op); +int WM_gesture_border_invoke (struct bContext *C, struct wmOperator *op, const struct wmEvent *event); +int WM_gesture_border_modal (struct bContext *C, struct wmOperator *op, const struct wmEvent *event); +void WM_gesture_border_cancel(struct bContext *C, struct wmOperator *op); int WM_gesture_circle_invoke(struct bContext *C, struct wmOperator *op, const struct wmEvent *event); int WM_gesture_circle_modal(struct bContext *C, struct wmOperator *op, const struct wmEvent *event); void WM_gesture_circle_cancel(struct bContext *C, struct wmOperator *op); diff --git a/source/blender/windowmanager/intern/wm_operator_props.c b/source/blender/windowmanager/intern/wm_operator_props.c index 569cd43a524..b8b52798175 100644 --- a/source/blender/windowmanager/intern/wm_operator_props.c +++ b/source/blender/windowmanager/intern/wm_operator_props.c @@ -225,7 +225,7 @@ void WM_operator_properties_border_to_rctf(struct wmOperator *op, rctf *rect) } /** - * Use with #WM_border_select_invoke + * Use with #WM_gesture_border_invoke */ void WM_operator_properties_gesture_border(wmOperatorType *ot, bool extend) { diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 307c8b24c1e..42f13257095 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -2312,7 +2312,7 @@ 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)) op->customdata = WM_gesture_new(C, event, WM_GESTURE_RECT); @@ -2327,7 +2327,7 @@ int WM_border_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) 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; @@ -2386,7 +2386,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); } -- cgit v1.2.3 From 870b4b673511094cf0beaeaf07305407ccdda47a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 16 Oct 2017 21:58:51 +1100 Subject: WM: refactor gestures for use as tools Border and circle select wait for input by default. This commit uses bool properties on the operators instead of magic number (called "gesture_mode"). Keymaps that define 'deselect' for border/circle select begin immediately, exiting when on button release. --- source/blender/windowmanager/WM_api.h | 8 +- source/blender/windowmanager/WM_types.h | 3 + source/blender/windowmanager/intern/wm_gesture.c | 1 + .../windowmanager/intern/wm_operator_props.c | 48 +++++++- source/blender/windowmanager/intern/wm_operators.c | 133 ++++++++++++++++----- source/blender/windowmanager/wm_event_types.h | 2 + 6 files changed, 161 insertions(+), 34 deletions(-) (limited to 'source/blender/windowmanager') diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index aa52e7d2248..595050e12f7 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -308,11 +308,17 @@ void WM_operator_properties_filesel( void WM_operator_properties_border(struct wmOperatorType *ot); void WM_operator_properties_border_to_rcti(struct wmOperator *op, struct rcti *rect); void WM_operator_properties_border_to_rctf(struct wmOperator *op, rctf *rect); -void WM_operator_properties_gesture_border(struct wmOperatorType *ot, bool extend); +void WM_operator_properties_gesture_border_ex(struct wmOperatorType *ot, bool deselect, bool extend); +void WM_operator_properties_gesture_border(struct wmOperatorType *ot); +void WM_operator_properties_gesture_border_select(struct wmOperatorType *ot); +void WM_operator_properties_gesture_border_zoom(struct wmOperatorType *ot); void WM_operator_properties_gesture_lasso_ex(struct wmOperatorType *ot, bool deselect, bool extend); void WM_operator_properties_gesture_lasso(struct wmOperatorType *ot); +void WM_operator_properties_gesture_lasso_select(struct wmOperatorType *ot); void WM_operator_properties_gesture_straightline(struct wmOperatorType *ot, int cursor); +void WM_operator_properties_gesture_circle_ex(struct wmOperatorType *ot, bool deselect); void WM_operator_properties_gesture_circle(struct wmOperatorType *ot); +void WM_operator_properties_gesture_circle_select(struct wmOperatorType *ot); void WM_operator_properties_mouse_select(struct wmOperatorType *ot); void WM_operator_properties_select_all(struct wmOperatorType *ot); void WM_operator_properties_select_action(struct wmOperatorType *ot, int default_action); diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index d8ec26f55da..6c47d61c535 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -413,10 +413,13 @@ typedef struct wmGesture { int swinid; /* initial subwindow id where it started */ int points; /* optional, amount of points stored */ int points_alloc; /* optional, maximum amount of points stored */ + int modal_state; /* For modal operators which may be running idle, waiting for an event to activate the gesture. * Typically this is set when the user is click-dragging the gesture (border and circle select for eg). */ uint is_active : 1; + /* Use for gestures that support both immediate or delayed activation. */ + uint wait_for_input : 1; void *customdata; /* customdata for border is a recti */ diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c index 11f39dc934c..b63962ffce2 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); diff --git a/source/blender/windowmanager/intern/wm_operator_props.c b/source/blender/windowmanager/intern/wm_operator_props.c index b8b52798175..4873a6bbf81 100644 --- a/source/blender/windowmanager/intern/wm_operator_props.c +++ b/source/blender/windowmanager/intern/wm_operator_props.c @@ -227,17 +227,36 @@ void WM_operator_properties_border_to_rctf(struct wmOperator *op, rctf *rect) /** * Use with #WM_gesture_border_invoke */ -void WM_operator_properties_gesture_border(wmOperatorType *ot, bool extend) +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_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); +} + /** * Use with #WM_gesture_lasso_invoke */ @@ -256,6 +275,11 @@ void WM_operator_properties_gesture_lasso_ex(wmOperatorType *ot, bool deselect, } 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); } @@ -286,7 +310,7 @@ void WM_operator_properties_gesture_straightline(wmOperatorType *ot, int cursor) /** * Use with #WM_gesture_circle_invoke */ -void WM_operator_properties_gesture_circle(wmOperatorType *ot) +void WM_operator_properties_gesture_circle_ex(wmOperatorType *ot, bool deselect) { PropertyRNA *prop; const int radius_default = 25; @@ -296,8 +320,20 @@ void WM_operator_properties_gesture_circle(wmOperatorType *ot) 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); - prop = RNA_def_int(ot->srna, "gesture_mode", 0, INT_MIN, INT_MAX, "Gesture Mode", "", INT_MIN, INT_MAX); - 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"); + } +} + +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) diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 42f13257095..9a1c01487b5 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -2250,6 +2250,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 *************** */ /** @@ -2260,7 +2297,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; @@ -2278,20 +2315,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); @@ -2314,14 +2349,28 @@ static void wm_gesture_end(bContext *C, wmOperator *op) 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; @@ -2344,7 +2393,7 @@ int WM_gesture_border_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); } @@ -2360,7 +2409,10 @@ int WM_gesture_border_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; } @@ -2394,8 +2446,12 @@ void WM_gesture_border_cancel(bContext *C, wmOperator *op) /* **************** circle gesture *************** */ /* works now only for selection or modal paint stuff, calls exec while hold mouse, exit on release */ +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; @@ -2403,6 +2459,16 @@ int WM_gesture_circle_invoke(bContext *C, wmOperator *op, const wmEvent *event) /* 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); @@ -2415,15 +2481,18 @@ 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); @@ -2451,6 +2520,7 @@ 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) { @@ -2476,12 +2546,16 @@ int WM_gesture_circle_modal(bContext *C, wmOperator *op, const wmEvent *event) case GESTURE_MODAL_DESELECT: case GESTURE_MODAL_NOP: { - PropertyRNA *prop = RNA_struct_find_property(op->ptr, "gesture_mode"); - if (prop != NULL) { - RNA_property_int_set(op->ptr, prop, event->val); + if (gesture->wait_for_input) { + gesture->modal_state = event->val; } - - if (event->val != GESTURE_MODAL_NOP) { + 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; @@ -2491,8 +2565,12 @@ int WM_gesture_circle_modal(bContext *C, wmOperator *op, const wmEvent *event) } 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) { @@ -4288,14 +4366,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); diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h index 3085f138846..090c8c90280 100644 --- a/source/blender/windowmanager/wm_event_types.h +++ b/source/blender/windowmanager/wm_event_types.h @@ -431,6 +431,7 @@ enum { GESTURE_MODAL_CANCEL = 1, GESTURE_MODAL_CONFIRM = 2, + /* Uses 'deselect' operator property. */ GESTURE_MODAL_SELECT = 3, GESTURE_MODAL_DESELECT = 4, @@ -441,6 +442,7 @@ enum { GESTURE_MODAL_BEGIN = 8, /* border select/straight line, activate, use release to detect which button */ + /* Uses 'zoom_out' operator property. */ GESTURE_MODAL_IN = 9, GESTURE_MODAL_OUT = 10, -- cgit v1.2.3