Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2017-10-16 13:58:51 +0300
committerCampbell Barton <ideasman42@gmail.com>2017-10-16 14:21:46 +0300
commit870b4b673511094cf0beaeaf07305407ccdda47a (patch)
treefb91f7c424f1971c35d537e520c519117e38f9d9 /source/blender/windowmanager
parent6d8f63a8343a6c0b44318f0a856dcd0fd0206131 (diff)
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.
Diffstat (limited to 'source/blender/windowmanager')
-rw-r--r--source/blender/windowmanager/WM_api.h8
-rw-r--r--source/blender/windowmanager/WM_types.h3
-rw-r--r--source/blender/windowmanager/intern/wm_gesture.c1
-rw-r--r--source/blender/windowmanager/intern/wm_operator_props.c48
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c133
-rw-r--r--source/blender/windowmanager/wm_event_types.h2
6 files changed, 161 insertions, 34 deletions
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
*/
@@ -257,6 +276,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,