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-17 07:18:12 +0300
committerCampbell Barton <ideasman42@gmail.com>2017-10-17 07:18:12 +0300
commitbb4c16ef94470fb3a9678235926577e8e7f042d0 (patch)
tree7831c80af3737a7b239e3e84d5462f08643877b4 /source/blender
parent0ffa64a45f7d961cb079a56629bcff105c81eb56 (diff)
parenta297e1bb93afcd2a216e074e6fd72c7914768cdf (diff)
Merge branch 'master' into blender2.8
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/windowmanager/CMakeLists.txt1
-rw-r--r--source/blender/windowmanager/WM_api.h2
-rw-r--r--source/blender/windowmanager/intern/wm_gesture_ops.c883
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c787
-rw-r--r--source/blender/windowmanager/wm.h5
5 files changed, 888 insertions, 790 deletions
diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt
index 8a6d4bc95c7..464906dad1e 100644
--- a/source/blender/windowmanager/CMakeLists.txt
+++ b/source/blender/windowmanager/CMakeLists.txt
@@ -63,6 +63,7 @@ set(SRC
intern/wm_files.c
intern/wm_files_link.c
intern/wm_gesture.c
+ intern/wm_gesture_ops.c
intern/wm_init_exit.c
intern/wm_jobs.c
intern/wm_keymap.c
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 8eab8662ea9..46aea519340 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -405,7 +405,7 @@ bool WM_menutype_add(struct MenuType *mt);
void WM_menutype_freelink(struct MenuType *mt);
void WM_menutype_free(void);
- /* default operator callbacks for border/circle/lasso */
+/* wm_gesture_ops.c */
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);
diff --git a/source/blender/windowmanager/intern/wm_gesture_ops.c b/source/blender/windowmanager/intern/wm_gesture_ops.c
new file mode 100644
index 00000000000..a554727cacd
--- /dev/null
+++ b/source/blender/windowmanager/intern/wm_gesture_ops.c
@@ -0,0 +1,883 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2007 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/windowmanager/intern/wm_gesture_ops.c
+ * \ingroup wm
+ *
+ * Default operator callbacks for use with gestures (border/circle/lasso/straightline).
+ * Operators themselves are defined elsewhere.
+ *
+ * - Keymaps are in ``wm_operators.c``.
+ * - Property definitions are in ``wm_operator_props.c``.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_windowmanager_types.h"
+
+#include "BLI_math.h"
+
+#include "BKE_context.h"
+
+#include "WM_types.h"
+#include "WM_api.h"
+
+#include "wm.h"
+#include "wm_event_types.h"
+#include "wm_event_system.h"
+#include "wm_subwindow.h"
+
+#include "ED_screen.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Internal Gesture Utilities
+ *
+ * Border gesture has two types:
+ * -# #WM_GESTURE_CROSS_RECT: starts a cross, on mouse click it changes to border.
+ * -# #WM_GESTURE_RECT: starts immediate as a border, on mouse click or release it ends.
+ *
+ * It stores 4 values (xmin, xmax, ymin, ymax) and event it ended with (event_type).
+ *
+ * \{ */
+
+static void gesture_modal_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));
+
+ if (RNA_struct_find_property(op->ptr, "cursor")) {
+ WM_cursor_modal_restore(CTX_wm_window(C));
+ }
+}
+
+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;
+}
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+/** \name Border Gesture
+ *
+ * Border gesture has two types:
+ * -# #WM_GESTURE_CROSS_RECT: starts a cross, on mouse click it changes to border.
+ * -# #WM_GESTURE_RECT: starts immediate as a border, on mouse click or release it ends.
+ *
+ * It stores 4 values (xmin, xmax, ymin, ymax) and event it ended with (event_type).
+ *
+ * \{ */
+
+static bool gesture_border_apply_rect(wmOperator *op)
+{
+ wmGesture *gesture = op->customdata;
+ rcti *rect = gesture->customdata;
+
+ if (rect->xmin == rect->xmax || rect->ymin == rect->ymax)
+ return 0;
+
+
+ /* operator arguments and storage. */
+ RNA_int_set(op->ptr, "xmin", min_ii(rect->xmin, rect->xmax));
+ RNA_int_set(op->ptr, "ymin", min_ii(rect->ymin, rect->ymax));
+ RNA_int_set(op->ptr, "xmax", max_ii(rect->xmin, rect->xmax));
+ RNA_int_set(op->ptr, "ymax", max_ii(rect->ymin, rect->ymax));
+
+ return 1;
+}
+
+static bool gesture_border_apply(bContext *C, wmOperator *op)
+{
+ wmGesture *gesture = op->customdata;
+
+ int retval;
+
+ if (!gesture_border_apply_rect(op)) {
+ return 0;
+ }
+
+ gesture_modal_state_to_operator(op, gesture->modal_state);
+
+ retval = op->type->exec(C, op);
+ OPERATOR_RETVAL_CHECK(retval);
+
+ return 1;
+}
+
+int WM_gesture_border_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ 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 {
+ 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_gesture_border_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ wmGesture *gesture = op->customdata;
+ rcti *rect = gesture->customdata;
+ int sx, sy;
+
+ if (event->type == MOUSEMOVE) {
+ wm_subwindow_origin_get(CTX_wm_window(C), gesture->swinid, &sx, &sy);
+
+ if (gesture->type == WM_GESTURE_CROSS_RECT && gesture->is_active == false) {
+ rect->xmin = rect->xmax = event->x - sx;
+ rect->ymin = rect->ymax = event->y - sy;
+ }
+ else {
+ rect->xmax = event->x - sx;
+ rect->ymax = event->y - sy;
+ }
+ gesture_border_apply_rect(op);
+
+ wm_gesture_tag_redraw(C);
+ }
+ else if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case GESTURE_MODAL_BEGIN:
+ if (gesture->type == WM_GESTURE_CROSS_RECT && gesture->is_active == false) {
+ gesture->is_active = true;
+ wm_gesture_tag_redraw(C);
+ }
+ break;
+ case GESTURE_MODAL_SELECT:
+ case GESTURE_MODAL_DESELECT:
+ case GESTURE_MODAL_IN:
+ case GESTURE_MODAL_OUT:
+ if (gesture->wait_for_input) {
+ gesture->modal_state = event->val;
+ }
+ if (gesture_border_apply(C, op)) {
+ gesture_modal_end(C, op);
+ return OPERATOR_FINISHED;
+ }
+ gesture_modal_end(C, op);
+ return OPERATOR_CANCELLED;
+
+ case GESTURE_MODAL_CANCEL:
+ gesture_modal_end(C, op);
+ return OPERATOR_CANCELLED;
+ }
+
+ }
+#ifdef WITH_INPUT_NDOF
+ else if (event->type == NDOF_MOTION) {
+ return OPERATOR_PASS_THROUGH;
+ }
+#endif
+
+#if 0
+ /* Allow view navigation??? */
+ else {
+ return OPERATOR_PASS_THROUGH;
+ }
+#endif
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void WM_gesture_border_cancel(bContext *C, wmOperator *op)
+{
+ gesture_modal_end(C, op);
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+/** \name Circle Gesture
+ *
+ * Currently only used for selection or modal paint stuff,
+ * calls ``exec`` while hold mouse, exits on release (with no difference between cancel and confirm).
+ *
+ * \{ */
+
+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);
+
+ wm_gesture_tag_redraw(C);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static void gesture_circle_apply(bContext *C, wmOperator *op)
+{
+ wmGesture *gesture = op->customdata;
+ rcti *rect = gesture->customdata;
+
+ 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);
+ }
+}
+
+int WM_gesture_circle_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ wmGesture *gesture = op->customdata;
+ rcti *rect = gesture->customdata;
+ int sx, sy;
+
+ if (event->type == MOUSEMOVE) {
+ wm_subwindow_origin_get(CTX_wm_window(C), gesture->swinid, &sx, &sy);
+
+ rect->xmin = event->x - sx;
+ rect->ymin = event->y - sy;
+
+ wm_gesture_tag_redraw(C);
+
+ if (gesture->is_active) {
+ gesture_circle_apply(C, op);
+ }
+ }
+ else if (event->type == EVT_MODAL_MAP) {
+ bool is_circle_size = false;
+ bool is_finished = false;
+ float fac;
+
+ switch (event->val) {
+ case GESTURE_MODAL_CIRCLE_SIZE:
+ fac = 0.3f * (event->y - event->prevy);
+ if (fac > 0)
+ rect->xmax += ceil(fac);
+ else
+ rect->xmax += floor(fac);
+ if (rect->xmax < 1) rect->xmax = 1;
+ is_circle_size = true;
+ break;
+ case GESTURE_MODAL_CIRCLE_ADD:
+ rect->xmax += 2 + rect->xmax / 10;
+ is_circle_size = true;
+ break;
+ case GESTURE_MODAL_CIRCLE_SUB:
+ rect->xmax -= 2 + rect->xmax / 10;
+ if (rect->xmax < 1) rect->xmax = 1;
+ is_circle_size = true;
+ break;
+ case GESTURE_MODAL_SELECT:
+ case GESTURE_MODAL_DESELECT:
+ case 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:
+ is_finished = true;
+ }
+
+ if (is_finished) {
+ gesture_modal_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) {
+ return OPERATOR_PASS_THROUGH;
+ }
+#endif
+
+#if 0
+ /* Allow view navigation??? */
+ /* note, this gives issues:
+ * 1) other modal ops run on top (border select),
+ * 2) middlemouse is used now 3) tablet/trackpad? */
+ else {
+ return OPERATOR_PASS_THROUGH;
+ }
+#endif
+
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void WM_gesture_circle_cancel(bContext *C, wmOperator *op)
+{
+ gesture_modal_end(C, op);
+}
+
+#if 0
+/* template to copy from */
+void WM_OT_circle_gesture(wmOperatorType *ot)
+{
+ ot->name = "Circle Gesture";
+ ot->idname = "WM_OT_circle_gesture";
+ ot->description = "Enter rotate mode with a circular gesture";
+
+ ot->invoke = WM_gesture_circle_invoke;
+ ot->modal = WM_gesture_circle_modal;
+ ot->poll = WM_operator_winactive;
+
+ /* properties */
+ WM_operator_properties_gesture_circle(ot);
+
+}
+#endif
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+/** \name Tweak Gesture
+ * \{ */
+
+static void gesture_tweak_modal(bContext *C, const wmEvent *event)
+{
+ wmWindow *window = CTX_wm_window(C);
+ wmGesture *gesture = window->tweak;
+ rcti *rect = gesture->customdata;
+ int sx, sy, val;
+
+ switch (event->type) {
+ case MOUSEMOVE:
+ case INBETWEEN_MOUSEMOVE:
+
+ wm_subwindow_origin_get(window, gesture->swinid, &sx, &sy);
+
+ rect->xmax = event->x - sx;
+ rect->ymax = event->y - sy;
+
+ if ((val = wm_gesture_evaluate(gesture))) {
+ wmEvent tevent;
+
+ wm_event_init_from_window(window, &tevent);
+ /* We want to get coord from start of drag, not from point where it becomes a tweak event, see T40549 */
+ tevent.x = rect->xmin + sx;
+ tevent.y = rect->ymin + sy;
+ if (gesture->event_type == LEFTMOUSE)
+ tevent.type = EVT_TWEAK_L;
+ else if (gesture->event_type == RIGHTMOUSE)
+ tevent.type = EVT_TWEAK_R;
+ else
+ tevent.type = EVT_TWEAK_M;
+ tevent.val = val;
+ /* mouse coords! */
+
+ /* important we add immediately after this event, so future mouse releases
+ * (which may be in the queue already), are handled in order, see T44740 */
+ wm_event_add_ex(window, &tevent, event);
+
+ WM_gesture_end(C, gesture); /* frees gesture itself, and unregisters from window */
+ }
+
+ break;
+
+ case LEFTMOUSE:
+ case RIGHTMOUSE:
+ case MIDDLEMOUSE:
+ if (gesture->event_type == event->type) {
+ WM_gesture_end(C, gesture);
+
+ /* when tweak fails we should give the other keymap entries a chance */
+
+ /* XXX, assigning to readonly, BAD JUJU! */
+ ((wmEvent *)event)->val = KM_RELEASE;
+ }
+ break;
+ default:
+ if (!ISTIMER(event->type) && event->type != EVENT_NONE) {
+ WM_gesture_end(C, gesture);
+ }
+ break;
+ }
+}
+
+/* standard tweak, called after window handlers passed on event */
+void wm_tweakevent_test(bContext *C, const wmEvent *event, int action)
+{
+ wmWindow *win = CTX_wm_window(C);
+
+ if (win->tweak == NULL) {
+ if (CTX_wm_region(C)) {
+ if (event->val == KM_PRESS) {
+ if (ELEM(event->type, LEFTMOUSE, MIDDLEMOUSE, RIGHTMOUSE)) {
+ win->tweak = WM_gesture_new(C, event, WM_GESTURE_TWEAK);
+ }
+ }
+ }
+ }
+ else {
+ /* no tweaks if event was handled */
+ if ((action & WM_HANDLER_BREAK)) {
+ WM_gesture_end(C, win->tweak);
+ }
+ else
+ gesture_tweak_modal(C, event);
+ }
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+/** \name Lasso Gesture
+ * \{ */
+
+int WM_gesture_lasso_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ PropertyRNA *prop;
+
+ op->customdata = WM_gesture_new(C, event, WM_GESTURE_LASSO);
+
+ /* add modal handler */
+ WM_event_add_modal_handler(C, op);
+
+ wm_gesture_tag_redraw(C);
+
+ if ((prop = RNA_struct_find_property(op->ptr, "cursor"))) {
+ WM_cursor_modal_set(CTX_wm_window(C), RNA_property_int_get(op->ptr, prop));
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+int WM_gesture_lines_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ PropertyRNA *prop;
+
+ op->customdata = WM_gesture_new(C, event, WM_GESTURE_LINES);
+
+ /* add modal handler */
+ WM_event_add_modal_handler(C, op);
+
+ wm_gesture_tag_redraw(C);
+
+ if ((prop = RNA_struct_find_property(op->ptr, "cursor"))) {
+ WM_cursor_modal_set(CTX_wm_window(C), RNA_property_int_get(op->ptr, prop));
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+
+static void gesture_lasso_apply(bContext *C, wmOperator *op)
+{
+ wmGesture *gesture = op->customdata;
+ PointerRNA itemptr;
+ float loc[2];
+ int i;
+ const short *lasso = gesture->customdata;
+
+ /* operator storage as path. */
+
+ RNA_collection_clear(op->ptr, "path");
+ for (i = 0; i < gesture->points; i++, lasso += 2) {
+ loc[0] = lasso[0];
+ loc[1] = lasso[1];
+ RNA_collection_add(op->ptr, "path", &itemptr);
+ RNA_float_set_array(&itemptr, "loc", loc);
+ }
+
+ gesture_modal_end(C, op);
+
+ if (op->type->exec) {
+ int retval = op->type->exec(C, op);
+ OPERATOR_RETVAL_CHECK(retval);
+ }
+}
+
+int WM_gesture_lasso_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ wmGesture *gesture = op->customdata;
+ int sx, sy;
+
+ switch (event->type) {
+ case MOUSEMOVE:
+ case INBETWEEN_MOUSEMOVE:
+
+ wm_gesture_tag_redraw(C);
+
+ wm_subwindow_origin_get(CTX_wm_window(C), gesture->swinid, &sx, &sy);
+
+ if (gesture->points == gesture->points_alloc) {
+ gesture->points_alloc *= 2;
+ gesture->customdata = MEM_reallocN(gesture->customdata, sizeof(short[2]) * gesture->points_alloc);
+ }
+
+ {
+ int x, y;
+ short *lasso = gesture->customdata;
+
+ lasso += (2 * gesture->points - 2);
+ x = (event->x - sx - lasso[0]);
+ y = (event->y - sy - lasso[1]);
+
+ /* make a simple distance check to get a smoother lasso
+ * add only when at least 2 pixels between this and previous location */
+ if ((x * x + y * y) > 4) {
+ lasso += 2;
+ lasso[0] = event->x - sx;
+ lasso[1] = event->y - sy;
+ gesture->points++;
+ }
+ }
+ break;
+
+ case LEFTMOUSE:
+ case MIDDLEMOUSE:
+ case RIGHTMOUSE:
+ if (event->val == KM_RELEASE) { /* key release */
+ gesture_lasso_apply(C, op);
+ return OPERATOR_FINISHED;
+ }
+ break;
+ case ESCKEY:
+ gesture_modal_end(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ return OPERATOR_RUNNING_MODAL;
+}
+
+int WM_gesture_lines_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ return WM_gesture_lasso_modal(C, op, event);
+}
+
+void WM_gesture_lasso_cancel(bContext *C, wmOperator *op)
+{
+ gesture_modal_end(C, op);
+}
+
+void WM_gesture_lines_cancel(bContext *C, wmOperator *op)
+{
+ gesture_modal_end(C, op);
+}
+
+/**
+ * helper function, we may want to add options for conversion to view space
+ *
+ * caller must free.
+ */
+const int (*WM_gesture_lasso_path_to_array(bContext *UNUSED(C), wmOperator *op, int *mcords_tot))[2]
+{
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "path");
+ int (*mcords)[2] = NULL;
+ BLI_assert(prop != NULL);
+
+ if (prop) {
+ const int len = RNA_property_collection_length(op->ptr, prop);
+
+ if (len) {
+ int i = 0;
+ mcords = MEM_mallocN(sizeof(int) * 2 * len, __func__);
+
+ RNA_PROP_BEGIN (op->ptr, itemptr, prop)
+ {
+ float loc[2];
+
+ RNA_float_get_array(&itemptr, "loc", loc);
+ mcords[i][0] = (int)loc[0];
+ mcords[i][1] = (int)loc[1];
+ i++;
+ }
+ RNA_PROP_END;
+ }
+ *mcords_tot = len;
+ }
+ else {
+ *mcords_tot = 0;
+ }
+
+ /* cast for 'const' */
+ return (const int (*)[2])mcords;
+}
+
+#if 0
+/* template to copy from */
+
+static int gesture_lasso_exec(bContext *C, wmOperator *op)
+{
+ RNA_BEGIN (op->ptr, itemptr, "path")
+ {
+ float loc[2];
+
+ RNA_float_get_array(&itemptr, "loc", loc);
+ printf("Location: %f %f\n", loc[0], loc[1]);
+ }
+ RNA_END;
+
+ return OPERATOR_FINISHED;
+}
+
+void WM_OT_lasso_gesture(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ ot->name = "Lasso Gesture";
+ ot->idname = "WM_OT_lasso_gesture";
+ ot->description = "Select objects within the lasso as you move the pointer";
+
+ ot->invoke = WM_gesture_lasso_invoke;
+ ot->modal = WM_gesture_lasso_modal;
+ ot->exec = gesture_lasso_exec;
+
+ ot->poll = WM_operator_winactive;
+
+ prop = RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
+}
+#endif
+
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+/** \name Straight Line Gesture
+ * \{ */
+
+static bool gesture_straightline_apply(bContext *C, wmOperator *op)
+{
+ wmGesture *gesture = op->customdata;
+ rcti *rect = gesture->customdata;
+
+ if (rect->xmin == rect->xmax && rect->ymin == rect->ymax)
+ return 0;
+
+ /* operator arguments and storage. */
+ RNA_int_set(op->ptr, "xstart", rect->xmin);
+ RNA_int_set(op->ptr, "ystart", rect->ymin);
+ RNA_int_set(op->ptr, "xend", rect->xmax);
+ RNA_int_set(op->ptr, "yend", rect->ymax);
+
+ if (op->type->exec) {
+ int retval = op->type->exec(C, op);
+ OPERATOR_RETVAL_CHECK(retval);
+ }
+
+ return 1;
+}
+
+int WM_gesture_straightline_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ PropertyRNA *prop;
+
+ op->customdata = WM_gesture_new(C, event, WM_GESTURE_STRAIGHTLINE);
+
+ if (ISTWEAK(event->type)) {
+ wmGesture *gesture = op->customdata;
+ gesture->is_active = true;
+ }
+
+ /* add modal handler */
+ WM_event_add_modal_handler(C, op);
+
+ wm_gesture_tag_redraw(C);
+
+ if ((prop = RNA_struct_find_property(op->ptr, "cursor"))) {
+ WM_cursor_modal_set(CTX_wm_window(C), RNA_property_int_get(op->ptr, prop));
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+int WM_gesture_straightline_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ wmGesture *gesture = op->customdata;
+ rcti *rect = gesture->customdata;
+ int sx, sy;
+
+ if (event->type == MOUSEMOVE) {
+ wm_subwindow_origin_get(CTX_wm_window(C), gesture->swinid, &sx, &sy);
+
+ if (gesture->is_active == false) {
+ rect->xmin = rect->xmax = event->x - sx;
+ rect->ymin = rect->ymax = event->y - sy;
+ }
+ else {
+ rect->xmax = event->x - sx;
+ rect->ymax = event->y - sy;
+ gesture_straightline_apply(C, op);
+ }
+
+ wm_gesture_tag_redraw(C);
+ }
+ else if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case GESTURE_MODAL_BEGIN:
+ if (gesture->is_active == false) {
+ gesture->is_active = true;
+ wm_gesture_tag_redraw(C);
+ }
+ break;
+ case GESTURE_MODAL_SELECT:
+ if (gesture_straightline_apply(C, op)) {
+ gesture_modal_end(C, op);
+ return OPERATOR_FINISHED;
+ }
+ gesture_modal_end(C, op);
+ return OPERATOR_CANCELLED;
+
+ case GESTURE_MODAL_CANCEL:
+ gesture_modal_end(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void WM_gesture_straightline_cancel(bContext *C, wmOperator *op)
+{
+ gesture_modal_end(C, op);
+}
+
+#if 0
+/* template to copy from */
+void WM_OT_straightline_gesture(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ ot->name = "Straight Line Gesture";
+ ot->idname = "WM_OT_straightline_gesture";
+ ot->description = "Draw a straight line as you move the pointer";
+
+ ot->invoke = WM_gesture_straightline_invoke;
+ ot->modal = WM_gesture_straightline_modal;
+ ot->exec = gesture_straightline_exec;
+
+ ot->poll = WM_operator_winactive;
+
+ WM_operator_properties_gesture_straightline(ot, 0);
+}
+#endif
+
+/** \} */
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 77dbecec9f0..a5b64c05156 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -115,7 +115,6 @@
#include "wm_event_system.h"
#include "wm_event_types.h"
#include "wm_files.h"
-#include "wm_subwindow.h"
#include "wm_window.h"
static GHash *global_ops_hash = NULL;
@@ -2298,792 +2297,6 @@ void WM_paint_cursor_end(wmWindowManager *wm, void *handle)
}
}
-/* ************ window gesture operator-callback definitions ************** */
-/*
- * 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 *************** */
-
-/**
- * Border gesture has two types:
- * -# #WM_GESTURE_CROSS_RECT: starts a cross, on mouse click it changes to border.
- * -# #WM_GESTURE_RECT: starts immediate as a border, on mouse click or release it ends.
- *
- * It stores 4 values (xmin, xmax, ymin, ymax) and event it ended with (event_type)
- */
-
-static bool gesture_border_apply_rect(wmOperator *op)
-{
- wmGesture *gesture = op->customdata;
- rcti *rect = gesture->customdata;
-
- if (rect->xmin == rect->xmax || rect->ymin == rect->ymax)
- return 0;
-
-
- /* operator arguments and storage. */
- RNA_int_set(op->ptr, "xmin", min_ii(rect->xmin, rect->xmax));
- RNA_int_set(op->ptr, "ymin", min_ii(rect->ymin, rect->ymax));
- RNA_int_set(op->ptr, "xmax", max_ii(rect->xmin, rect->xmax));
- RNA_int_set(op->ptr, "ymax", max_ii(rect->ymin, rect->ymax));
-
- return 1;
-}
-
-static bool gesture_border_apply(bContext *C, wmOperator *op)
-{
- wmGesture *gesture = op->customdata;
-
- int retval;
-
- if (!gesture_border_apply_rect(op)) {
- return 0;
- }
-
- gesture_modal_state_to_operator(op, gesture->modal_state);
-
- retval = op->type->exec(C, op);
- OPERATOR_RETVAL_CHECK(retval);
-
- return 1;
-}
-
-static void wm_gesture_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));
-
- if (RNA_struct_find_property(op->ptr, "cursor")) {
- WM_cursor_modal_restore(CTX_wm_window(C));
- }
-}
-
-int WM_gesture_border_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- 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 {
- 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_gesture_border_modal(bContext *C, wmOperator *op, const wmEvent *event)
-{
- wmGesture *gesture = op->customdata;
- rcti *rect = gesture->customdata;
- int sx, sy;
-
- if (event->type == MOUSEMOVE) {
- wm_subwindow_origin_get(CTX_wm_window(C), gesture->swinid, &sx, &sy);
-
- if (gesture->type == WM_GESTURE_CROSS_RECT && gesture->is_active == false) {
- rect->xmin = rect->xmax = event->x - sx;
- rect->ymin = rect->ymax = event->y - sy;
- }
- else {
- rect->xmax = event->x - sx;
- rect->ymax = event->y - sy;
- }
- gesture_border_apply_rect(op);
-
- wm_gesture_tag_redraw(C);
- }
- else if (event->type == EVT_MODAL_MAP) {
- switch (event->val) {
- case GESTURE_MODAL_BEGIN:
- if (gesture->type == WM_GESTURE_CROSS_RECT && gesture->is_active == false) {
- gesture->is_active = true;
- wm_gesture_tag_redraw(C);
- }
- break;
- case GESTURE_MODAL_SELECT:
- case GESTURE_MODAL_DESELECT:
- case GESTURE_MODAL_IN:
- case GESTURE_MODAL_OUT:
- if (gesture->wait_for_input) {
- gesture->modal_state = event->val;
- }
- if (gesture_border_apply(C, op)) {
- wm_gesture_end(C, op);
- return OPERATOR_FINISHED;
- }
- wm_gesture_end(C, op);
- return OPERATOR_CANCELLED;
-
- case GESTURE_MODAL_CANCEL:
- wm_gesture_end(C, op);
- return OPERATOR_CANCELLED;
- }
-
- }
-#ifdef WITH_INPUT_NDOF
- else if (event->type == NDOF_MOTION) {
- return OPERATOR_PASS_THROUGH;
- }
-#endif
-// /* Allow view navigation??? */
-// else {
-// return OPERATOR_PASS_THROUGH;
-// }
-
- return OPERATOR_RUNNING_MODAL;
-}
-
-void WM_gesture_border_cancel(bContext *C, wmOperator *op)
-{
- wm_gesture_end(C, 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;
-
- /* 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);
-
- wm_gesture_tag_redraw(C);
-
- return OPERATOR_RUNNING_MODAL;
-}
-
-static void gesture_circle_apply(bContext *C, wmOperator *op)
-{
- wmGesture *gesture = op->customdata;
- rcti *rect = gesture->customdata;
-
- 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);
- }
-}
-
-int WM_gesture_circle_modal(bContext *C, wmOperator *op, const wmEvent *event)
-{
- wmGesture *gesture = op->customdata;
- rcti *rect = gesture->customdata;
- int sx, sy;
-
- if (event->type == MOUSEMOVE) {
- wm_subwindow_origin_get(CTX_wm_window(C), gesture->swinid, &sx, &sy);
-
- rect->xmin = event->x - sx;
- rect->ymin = event->y - sy;
-
- wm_gesture_tag_redraw(C);
-
- if (gesture->is_active) {
- gesture_circle_apply(C, op);
- }
- }
- else if (event->type == EVT_MODAL_MAP) {
- bool is_circle_size = false;
- bool is_finished = false;
- float fac;
-
- switch (event->val) {
- case GESTURE_MODAL_CIRCLE_SIZE:
- fac = 0.3f * (event->y - event->prevy);
- if (fac > 0)
- rect->xmax += ceil(fac);
- else
- rect->xmax += floor(fac);
- if (rect->xmax < 1) rect->xmax = 1;
- is_circle_size = true;
- break;
- case GESTURE_MODAL_CIRCLE_ADD:
- rect->xmax += 2 + rect->xmax / 10;
- is_circle_size = true;
- break;
- case GESTURE_MODAL_CIRCLE_SUB:
- rect->xmax -= 2 + rect->xmax / 10;
- if (rect->xmax < 1) rect->xmax = 1;
- is_circle_size = true;
- break;
- case GESTURE_MODAL_SELECT:
- case GESTURE_MODAL_DESELECT:
- case 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:
- 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
- else if (event->type == NDOF_MOTION) {
- return OPERATOR_PASS_THROUGH;
- }
-#endif
- /* Allow view navigation??? */
- /* note, this gives issues: 1) other modal ops run on top (border select), 2) middlemouse is used now 3) tablet/trackpad? */
-// else {
-// return OPERATOR_PASS_THROUGH;
-// }
-
- return OPERATOR_RUNNING_MODAL;
-}
-
-void WM_gesture_circle_cancel(bContext *C, wmOperator *op)
-{
- wm_gesture_end(C, op);
-}
-
-#if 0
-/* template to copy from */
-void WM_OT_circle_gesture(wmOperatorType *ot)
-{
- ot->name = "Circle Gesture";
- ot->idname = "WM_OT_circle_gesture";
- ot->description = "Enter rotate mode with a circular gesture";
-
- ot->invoke = WM_gesture_circle_invoke;
- ot->modal = WM_gesture_circle_modal;
- ot->poll = WM_operator_winactive;
-
- /* properties */
- WM_operator_properties_gesture_circle(ot);
-
-}
-#endif
-
-/* **************** Tweak gesture *************** */
-
-static void tweak_gesture_modal(bContext *C, const wmEvent *event)
-{
- wmWindow *window = CTX_wm_window(C);
- wmGesture *gesture = window->tweak;
- rcti *rect = gesture->customdata;
- int sx, sy, val;
-
- switch (event->type) {
- case MOUSEMOVE:
- case INBETWEEN_MOUSEMOVE:
-
- wm_subwindow_origin_get(window, gesture->swinid, &sx, &sy);
-
- rect->xmax = event->x - sx;
- rect->ymax = event->y - sy;
-
- if ((val = wm_gesture_evaluate(gesture))) {
- wmEvent tevent;
-
- wm_event_init_from_window(window, &tevent);
- /* We want to get coord from start of drag, not from point where it becomes a tweak event, see T40549 */
- tevent.x = rect->xmin + sx;
- tevent.y = rect->ymin + sy;
- if (gesture->event_type == LEFTMOUSE)
- tevent.type = EVT_TWEAK_L;
- else if (gesture->event_type == RIGHTMOUSE)
- tevent.type = EVT_TWEAK_R;
- else
- tevent.type = EVT_TWEAK_M;
- tevent.val = val;
- /* mouse coords! */
-
- /* important we add immediately after this event, so future mouse releases
- * (which may be in the queue already), are handled in order, see T44740 */
- wm_event_add_ex(window, &tevent, event);
-
- WM_gesture_end(C, gesture); /* frees gesture itself, and unregisters from window */
- }
-
- break;
-
- case LEFTMOUSE:
- case RIGHTMOUSE:
- case MIDDLEMOUSE:
- if (gesture->event_type == event->type) {
- WM_gesture_end(C, gesture);
-
- /* when tweak fails we should give the other keymap entries a chance */
-
- /* XXX, assigning to readonly, BAD JUJU! */
- ((wmEvent *)event)->val = KM_RELEASE;
- }
- break;
- default:
- if (!ISTIMER(event->type) && event->type != EVENT_NONE) {
- WM_gesture_end(C, gesture);
- }
- break;
- }
-}
-
-/* standard tweak, called after window handlers passed on event */
-void wm_tweakevent_test(bContext *C, const wmEvent *event, int action)
-{
- wmWindow *win = CTX_wm_window(C);
-
- if (win->tweak == NULL) {
- if (CTX_wm_region(C)) {
- if (event->val == KM_PRESS) {
- if (ELEM(event->type, LEFTMOUSE, MIDDLEMOUSE, RIGHTMOUSE)) {
- win->tweak = WM_gesture_new(C, event, WM_GESTURE_TWEAK);
- }
- }
- }
- }
- else {
- /* no tweaks if event was handled */
- if ((action & WM_HANDLER_BREAK)) {
- WM_gesture_end(C, win->tweak);
- }
- else
- tweak_gesture_modal(C, event);
- }
-}
-
-/* *********************** lasso gesture ****************** */
-
-int WM_gesture_lasso_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- PropertyRNA *prop;
-
- op->customdata = WM_gesture_new(C, event, WM_GESTURE_LASSO);
-
- /* add modal handler */
- WM_event_add_modal_handler(C, op);
-
- wm_gesture_tag_redraw(C);
-
- if ((prop = RNA_struct_find_property(op->ptr, "cursor"))) {
- WM_cursor_modal_set(CTX_wm_window(C), RNA_property_int_get(op->ptr, prop));
- }
-
- return OPERATOR_RUNNING_MODAL;
-}
-
-int WM_gesture_lines_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- PropertyRNA *prop;
-
- op->customdata = WM_gesture_new(C, event, WM_GESTURE_LINES);
-
- /* add modal handler */
- WM_event_add_modal_handler(C, op);
-
- wm_gesture_tag_redraw(C);
-
- if ((prop = RNA_struct_find_property(op->ptr, "cursor"))) {
- WM_cursor_modal_set(CTX_wm_window(C), RNA_property_int_get(op->ptr, prop));
- }
-
- return OPERATOR_RUNNING_MODAL;
-}
-
-
-static void gesture_lasso_apply(bContext *C, wmOperator *op)
-{
- wmGesture *gesture = op->customdata;
- PointerRNA itemptr;
- float loc[2];
- int i;
- const short *lasso = gesture->customdata;
-
- /* operator storage as path. */
-
- RNA_collection_clear(op->ptr, "path");
- for (i = 0; i < gesture->points; i++, lasso += 2) {
- loc[0] = lasso[0];
- loc[1] = lasso[1];
- RNA_collection_add(op->ptr, "path", &itemptr);
- RNA_float_set_array(&itemptr, "loc", loc);
- }
-
- wm_gesture_end(C, op);
-
- if (op->type->exec) {
- int retval = op->type->exec(C, op);
- OPERATOR_RETVAL_CHECK(retval);
- }
-}
-
-int WM_gesture_lasso_modal(bContext *C, wmOperator *op, const wmEvent *event)
-{
- wmGesture *gesture = op->customdata;
- int sx, sy;
-
- switch (event->type) {
- case MOUSEMOVE:
- case INBETWEEN_MOUSEMOVE:
-
- wm_gesture_tag_redraw(C);
-
- wm_subwindow_origin_get(CTX_wm_window(C), gesture->swinid, &sx, &sy);
-
- if (gesture->points == gesture->points_alloc) {
- gesture->points_alloc *= 2;
- gesture->customdata = MEM_reallocN(gesture->customdata, sizeof(short[2]) * gesture->points_alloc);
- }
-
- {
- int x, y;
- short *lasso = gesture->customdata;
-
- lasso += (2 * gesture->points - 2);
- x = (event->x - sx - lasso[0]);
- y = (event->y - sy - lasso[1]);
-
- /* make a simple distance check to get a smoother lasso
- * add only when at least 2 pixels between this and previous location */
- if ((x * x + y * y) > 4) {
- lasso += 2;
- lasso[0] = event->x - sx;
- lasso[1] = event->y - sy;
- gesture->points++;
- }
- }
- break;
-
- case LEFTMOUSE:
- case MIDDLEMOUSE:
- case RIGHTMOUSE:
- if (event->val == KM_RELEASE) { /* key release */
- gesture_lasso_apply(C, op);
- return OPERATOR_FINISHED;
- }
- break;
- case ESCKEY:
- wm_gesture_end(C, op);
- return OPERATOR_CANCELLED;
- }
- return OPERATOR_RUNNING_MODAL;
-}
-
-int WM_gesture_lines_modal(bContext *C, wmOperator *op, const wmEvent *event)
-{
- return WM_gesture_lasso_modal(C, op, event);
-}
-
-void WM_gesture_lasso_cancel(bContext *C, wmOperator *op)
-{
- wm_gesture_end(C, op);
-}
-
-void WM_gesture_lines_cancel(bContext *C, wmOperator *op)
-{
- wm_gesture_end(C, op);
-}
-
-/**
- * helper function, we may want to add options for conversion to view space
- *
- * caller must free.
- */
-const int (*WM_gesture_lasso_path_to_array(bContext *UNUSED(C), wmOperator *op, int *mcords_tot))[2]
-{
- PropertyRNA *prop = RNA_struct_find_property(op->ptr, "path");
- int (*mcords)[2] = NULL;
- BLI_assert(prop != NULL);
-
- if (prop) {
- const int len = RNA_property_collection_length(op->ptr, prop);
-
- if (len) {
- int i = 0;
- mcords = MEM_mallocN(sizeof(int) * 2 * len, __func__);
-
- RNA_PROP_BEGIN (op->ptr, itemptr, prop)
- {
- float loc[2];
-
- RNA_float_get_array(&itemptr, "loc", loc);
- mcords[i][0] = (int)loc[0];
- mcords[i][1] = (int)loc[1];
- i++;
- }
- RNA_PROP_END;
- }
- *mcords_tot = len;
- }
- else {
- *mcords_tot = 0;
- }
-
- /* cast for 'const' */
- return (const int (*)[2])mcords;
-}
-
-#if 0
-/* template to copy from */
-
-static int gesture_lasso_exec(bContext *C, wmOperator *op)
-{
- RNA_BEGIN (op->ptr, itemptr, "path")
- {
- float loc[2];
-
- RNA_float_get_array(&itemptr, "loc", loc);
- printf("Location: %f %f\n", loc[0], loc[1]);
- }
- RNA_END;
-
- return OPERATOR_FINISHED;
-}
-
-void WM_OT_lasso_gesture(wmOperatorType *ot)
-{
- PropertyRNA *prop;
-
- ot->name = "Lasso Gesture";
- ot->idname = "WM_OT_lasso_gesture";
- ot->description = "Select objects within the lasso as you move the pointer";
-
- ot->invoke = WM_gesture_lasso_invoke;
- ot->modal = WM_gesture_lasso_modal;
- ot->exec = gesture_lasso_exec;
-
- ot->poll = WM_operator_winactive;
-
- prop = RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
-}
-#endif
-
-/* *********************** straight line gesture ****************** */
-
-static int straightline_apply(bContext *C, wmOperator *op)
-{
- wmGesture *gesture = op->customdata;
- rcti *rect = gesture->customdata;
-
- if (rect->xmin == rect->xmax && rect->ymin == rect->ymax)
- return 0;
-
- /* operator arguments and storage. */
- RNA_int_set(op->ptr, "xstart", rect->xmin);
- RNA_int_set(op->ptr, "ystart", rect->ymin);
- RNA_int_set(op->ptr, "xend", rect->xmax);
- RNA_int_set(op->ptr, "yend", rect->ymax);
-
- if (op->type->exec) {
- int retval = op->type->exec(C, op);
- OPERATOR_RETVAL_CHECK(retval);
- }
-
- return 1;
-}
-
-
-int WM_gesture_straightline_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- PropertyRNA *prop;
-
- op->customdata = WM_gesture_new(C, event, WM_GESTURE_STRAIGHTLINE);
-
- if (ISTWEAK(event->type)) {
- wmGesture *gesture = op->customdata;
- gesture->is_active = true;
- }
-
- /* add modal handler */
- WM_event_add_modal_handler(C, op);
-
- wm_gesture_tag_redraw(C);
-
- if ((prop = RNA_struct_find_property(op->ptr, "cursor"))) {
- WM_cursor_modal_set(CTX_wm_window(C), RNA_property_int_get(op->ptr, prop));
- }
-
- return OPERATOR_RUNNING_MODAL;
-}
-
-int WM_gesture_straightline_modal(bContext *C, wmOperator *op, const wmEvent *event)
-{
- wmGesture *gesture = op->customdata;
- rcti *rect = gesture->customdata;
- int sx, sy;
-
- if (event->type == MOUSEMOVE) {
- wm_subwindow_origin_get(CTX_wm_window(C), gesture->swinid, &sx, &sy);
-
- if (gesture->is_active == false) {
- rect->xmin = rect->xmax = event->x - sx;
- rect->ymin = rect->ymax = event->y - sy;
- }
- else {
- rect->xmax = event->x - sx;
- rect->ymax = event->y - sy;
- straightline_apply(C, op);
- }
-
- wm_gesture_tag_redraw(C);
- }
- else if (event->type == EVT_MODAL_MAP) {
- switch (event->val) {
- case GESTURE_MODAL_BEGIN:
- if (gesture->is_active == false) {
- gesture->is_active = true;
- wm_gesture_tag_redraw(C);
- }
- break;
- case GESTURE_MODAL_SELECT:
- if (straightline_apply(C, op)) {
- wm_gesture_end(C, op);
- return OPERATOR_FINISHED;
- }
- wm_gesture_end(C, op);
- return OPERATOR_CANCELLED;
-
- case GESTURE_MODAL_CANCEL:
- wm_gesture_end(C, op);
- return OPERATOR_CANCELLED;
- }
-
- }
-
- return OPERATOR_RUNNING_MODAL;
-}
-
-void WM_gesture_straightline_cancel(bContext *C, wmOperator *op)
-{
- wm_gesture_end(C, op);
-}
-
-#if 0
-/* template to copy from */
-void WM_OT_straightline_gesture(wmOperatorType *ot)
-{
- PropertyRNA *prop;
-
- ot->name = "Straight Line Gesture";
- ot->idname = "WM_OT_straightline_gesture";
- ot->description = "Draw a straight line as you move the pointer";
-
- ot->invoke = WM_gesture_straightline_invoke;
- ot->modal = WM_gesture_straightline_modal;
- ot->exec = gesture_straightline_exec;
-
- ot->poll = WM_operator_winactive;
-
- WM_operator_properties_gesture_straightline(ot, 0);
-}
-#endif
-
/* *********************** radial control ****************** */
#define WM_RADIAL_CONTROL_DISPLAY_SIZE (200 * UI_DPI_FAC)
diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h
index 01c8d6c1999..83d20aa2612 100644
--- a/source/blender/windowmanager/wm.h
+++ b/source/blender/windowmanager/wm.h
@@ -59,13 +59,14 @@ void wm_operatortype_free(void);
void wm_operatortype_init(void);
void wm_window_keymap(wmKeyConfig *keyconf);
-void wm_tweakevent_test(bContext *C, const wmEvent *event, int action);
-
/* wm_gesture.c */
void wm_gesture_draw(struct wmWindow *win);
int wm_gesture_evaluate(wmGesture *gesture);
void wm_gesture_tag_redraw(bContext *C);
+/* wm_gesture_ops.c */
+void wm_tweakevent_test(bContext *C, const wmEvent *event, int action);
+
/* wm_jobs.c */
void wm_jobs_timer(const bContext *C, wmWindowManager *wm, wmTimer *wt);
void wm_jobs_timer_ended(wmWindowManager *wm, wmTimer *wt);