Blender  V3.3
wm_gesture_ops.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2007 Blender Foundation. All rights reserved. */
3 
14 #include "MEM_guardedalloc.h"
15 
17 
18 #include "BLI_math.h"
19 #include "BLI_rect.h"
20 
21 #include "BKE_context.h"
22 
23 #include "WM_api.h"
24 #include "WM_types.h"
25 
26 #include "wm.h"
27 #include "wm_event_system.h"
28 #include "wm_event_types.h"
29 
30 #include "ED_screen.h"
31 #include "ED_select_utils.h"
32 
33 #include "UI_interface.h"
34 
35 #include "RNA_access.h"
36 #include "RNA_define.h"
37 
38 /* -------------------------------------------------------------------- */
50 {
51  wmWindow *win = CTX_wm_window(C);
52  wmGesture *gesture = op->customdata;
53 
54  WM_gesture_end(win, gesture); /* frees gesture itself, and unregisters from window */
55  op->customdata = NULL;
56 
58 
59  if (RNA_struct_find_property(op->ptr, "cursor")) {
61  }
62 }
63 
64 static void gesture_modal_state_to_operator(wmOperator *op, int modal_state)
65 {
66  PropertyRNA *prop;
67 
68  switch (modal_state) {
71  if ((prop = RNA_struct_find_property(op->ptr, "deselect"))) {
72  RNA_property_boolean_set(op->ptr, prop, (modal_state == GESTURE_MODAL_DESELECT));
73  }
74  if ((prop = RNA_struct_find_property(op->ptr, "mode"))) {
76  op->ptr, prop, (modal_state == GESTURE_MODAL_DESELECT) ? SEL_OP_SUB : SEL_OP_ADD);
77  }
78  break;
79  case GESTURE_MODAL_IN:
80  case GESTURE_MODAL_OUT:
81  if ((prop = RNA_struct_find_property(op->ptr, "zoom_out"))) {
82  RNA_property_boolean_set(op->ptr, prop, (modal_state == GESTURE_MODAL_OUT));
83  }
84  break;
85  }
86 }
87 
89 {
90  PropertyRNA *prop;
91 
92  if ((prop = RNA_struct_find_property(op->ptr, "deselect"))) {
93  if (RNA_property_is_set(op->ptr, prop)) {
94  return RNA_property_boolean_get(op->ptr, prop) ? GESTURE_MODAL_DESELECT :
96  }
97  }
98  if ((prop = RNA_struct_find_property(op->ptr, "mode"))) {
99  if (RNA_property_is_set(op->ptr, prop)) {
100  return RNA_property_enum_get(op->ptr, prop) == SEL_OP_SUB ? GESTURE_MODAL_DESELECT :
102  }
103  }
104  if ((prop = RNA_struct_find_property(op->ptr, "zoom_out"))) {
105  if (RNA_property_is_set(op->ptr, prop)) {
107  }
108  }
109  return GESTURE_MODAL_NOP;
110 }
111 
114 /* -------------------------------------------------------------------- */
126 {
127  wmGesture *gesture = op->customdata;
128  rcti *rect = gesture->customdata;
129 
130  if (rect->xmin == rect->xmax || rect->ymin == rect->ymax) {
131  return 0;
132  }
133 
134  /* operator arguments and storage. */
135  RNA_int_set(op->ptr, "xmin", min_ii(rect->xmin, rect->xmax));
136  RNA_int_set(op->ptr, "ymin", min_ii(rect->ymin, rect->ymax));
137  RNA_int_set(op->ptr, "xmax", max_ii(rect->xmin, rect->xmax));
138  RNA_int_set(op->ptr, "ymax", max_ii(rect->ymin, rect->ymax));
139 
140  return 1;
141 }
142 
144 {
145  wmGesture *gesture = op->customdata;
146 
147  int retval;
148 
149  if (!gesture_box_apply_rect(op)) {
150  return 0;
151  }
152 
153  if (gesture->wait_for_input) {
155  }
156 
157  retval = op->type->exec(C, op);
158  OPERATOR_RETVAL_CHECK(retval);
159 
160  return 1;
161 }
162 
164 {
165  wmWindow *win = CTX_wm_window(C);
166  const ARegion *region = CTX_wm_region(C);
167  const bool wait_for_input = !WM_event_is_mouse_drag_or_press(event) &&
168  RNA_boolean_get(op->ptr, "wait_for_input");
169 
170  if (wait_for_input) {
171  op->customdata = WM_gesture_new(win, region, event, WM_GESTURE_CROSS_RECT);
172  }
173  else {
174  op->customdata = WM_gesture_new(win, region, event, WM_GESTURE_RECT);
175  }
176 
177  {
178  wmGesture *gesture = op->customdata;
179  gesture->wait_for_input = wait_for_input;
180  }
181 
182  /* add modal handler */
184 
186 
187  return OPERATOR_RUNNING_MODAL;
188 }
189 
191 {
192  wmWindow *win = CTX_wm_window(C);
193  wmGesture *gesture = op->customdata;
194  rcti *rect = gesture->customdata;
195 
196  if (event->type == EVT_MODAL_MAP) {
197  switch (event->val) {
198  case GESTURE_MODAL_MOVE: {
199  gesture->move = !gesture->move;
200  break;
201  }
202  case GESTURE_MODAL_BEGIN: {
203  if (gesture->type == WM_GESTURE_CROSS_RECT && gesture->is_active == false) {
204  gesture->is_active = true;
206  }
207  break;
208  }
211  case GESTURE_MODAL_IN:
212  case GESTURE_MODAL_OUT: {
213  if (gesture->wait_for_input) {
214  gesture->modal_state = event->val;
215  }
216  if (gesture_box_apply(C, op)) {
217  gesture_modal_end(C, op);
218  return OPERATOR_FINISHED;
219  }
220  gesture_modal_end(C, op);
221  return OPERATOR_CANCELLED;
222  }
223  case GESTURE_MODAL_CANCEL: {
224  gesture_modal_end(C, op);
225  return OPERATOR_CANCELLED;
226  }
227  }
228  }
229  else {
230  switch (event->type) {
231  case MOUSEMOVE: {
232  if (gesture->type == WM_GESTURE_CROSS_RECT && gesture->is_active == false) {
233  rect->xmin = rect->xmax = event->xy[0] - gesture->winrct.xmin;
234  rect->ymin = rect->ymax = event->xy[1] - gesture->winrct.ymin;
235  }
236  else if (gesture->move) {
237  BLI_rcti_translate(rect,
238  (event->xy[0] - gesture->winrct.xmin) - rect->xmax,
239  (event->xy[1] - gesture->winrct.ymin) - rect->ymax);
240  }
241  else {
242  rect->xmax = event->xy[0] - gesture->winrct.xmin;
243  rect->ymax = event->xy[1] - gesture->winrct.ymin;
244  }
246 
248 
249  break;
250  }
251 #ifdef WITH_INPUT_NDOF
252  case NDOF_MOTION: {
253  return OPERATOR_PASS_THROUGH;
254  }
255 #endif
256 
257 #if 0 /* This allows view navigation, keep disabled as it's too unpredictable. */
258  default:
259  return OPERATOR_PASS_THROUGH;
260 #endif
261  }
262  }
263 
264  gesture->is_active_prev = gesture->is_active;
265  return OPERATOR_RUNNING_MODAL;
266 }
267 
269 {
270  gesture_modal_end(C, op);
271 }
272 
275 /* -------------------------------------------------------------------- */
284 static void gesture_circle_apply(bContext *C, wmOperator *op);
285 
287 {
288  wmWindow *win = CTX_wm_window(C);
289  const bool wait_for_input = !WM_event_is_mouse_drag_or_press(event) &&
290  RNA_boolean_get(op->ptr, "wait_for_input");
291 
293  wmGesture *gesture = op->customdata;
294  rcti *rect = gesture->customdata;
295 
296  /* Default or previously stored value. */
297  rect->xmax = RNA_int_get(op->ptr, "radius");
298 
299  gesture->wait_for_input = wait_for_input;
300 
301  /* Starting with the mode starts immediately,
302  * like having 'wait_for_input' disabled (some tools use this). */
303  if (gesture->wait_for_input == false) {
304  gesture->is_active = true;
305  gesture_circle_apply(C, op);
306  gesture->is_active_prev = true;
307  }
308 
309  /* add modal handler */
311 
313 
314  return OPERATOR_RUNNING_MODAL;
315 }
316 
318 {
319  wmGesture *gesture = op->customdata;
320  rcti *rect = gesture->customdata;
321 
322  if (gesture->wait_for_input && (gesture->modal_state == GESTURE_MODAL_NOP)) {
323  return;
324  }
325 
326  /* operator arguments and storage. */
327  RNA_int_set(op->ptr, "x", rect->xmin);
328  RNA_int_set(op->ptr, "y", rect->ymin);
329  RNA_int_set(op->ptr, "radius", rect->xmax);
330 
331  /* When 'wait_for_input' is false,
332  * use properties to get the selection state (typically tool settings).
333  * This is done so executing as a mode can select & de-select, see: T58594. */
334  if (gesture->wait_for_input) {
336  }
337 
338  if (op->type->exec) {
339  int retval;
340  retval = op->type->exec(C, op);
341  OPERATOR_RETVAL_CHECK(retval);
342  }
343 }
344 
346 {
347  wmWindow *win = CTX_wm_window(C);
348  wmGesture *gesture = op->customdata;
349  rcti *rect = gesture->customdata;
350 
351  if (event->type == MOUSEMOVE) {
352 
353  rect->xmin = event->xy[0] - gesture->winrct.xmin;
354  rect->ymin = event->xy[1] - gesture->winrct.ymin;
355 
357 
358  if (gesture->is_active) {
359  gesture_circle_apply(C, op);
360  }
361  }
362  else if (event->type == EVT_MODAL_MAP) {
363  bool is_circle_size = false;
364  bool is_finished = false;
365  float fac;
366 
367  switch (event->val) {
369  fac = 0.3f * (event->xy[1] - event->prev_xy[1]);
370  if (fac > 0) {
371  rect->xmax += ceil(fac);
372  }
373  else {
374  rect->xmax += floor(fac);
375  }
376  if (rect->xmax < 1) {
377  rect->xmax = 1;
378  }
379  is_circle_size = true;
380  break;
382  rect->xmax += 2 + rect->xmax / 10;
383  is_circle_size = true;
384  break;
386  rect->xmax -= 2 + rect->xmax / 10;
387  if (rect->xmax < 1) {
388  rect->xmax = 1;
389  }
390  is_circle_size = true;
391  break;
394  case GESTURE_MODAL_NOP: {
395  if (gesture->wait_for_input) {
396  gesture->modal_state = event->val;
397  }
398  if (event->val == GESTURE_MODAL_NOP) {
399  /* Single action, click-drag & release to exit. */
400  if (gesture->wait_for_input == false) {
401  is_finished = true;
402  }
403  }
404  else {
405  /* apply first click */
406  gesture->is_active = true;
407  gesture_circle_apply(C, op);
409  }
410  break;
411  }
414  is_finished = true;
415  }
416 
417  if (is_finished) {
418  gesture_modal_end(C, op);
419  return OPERATOR_FINISHED; /* use finish or we don't get an undo */
420  }
421 
422  if (is_circle_size) {
424 
425  /* So next use remembers last seen size, even if we didn't apply it. */
426  RNA_int_set(op->ptr, "radius", rect->xmax);
427  }
428  }
429 #ifdef WITH_INPUT_NDOF
430  else if (event->type == NDOF_MOTION) {
431  return OPERATOR_PASS_THROUGH;
432  }
433 #endif
434 
435 #if 0
436  /* Allow view navigation??? */
437  /* NOTE: this gives issues:
438  * 1) other modal ops run on top (box select),
439  * 2) middle-mouse is used now 3) tablet/trackpad? */
440  else {
441  return OPERATOR_PASS_THROUGH;
442  }
443 #endif
444 
445  gesture->is_active_prev = gesture->is_active;
446  return OPERATOR_RUNNING_MODAL;
447 }
448 
450 {
451  gesture_modal_end(C, op);
452 }
453 
454 #if 0
455 /* template to copy from */
456 void WM_OT_circle_gesture(wmOperatorType *ot)
457 {
458  ot->name = "Circle Gesture";
459  ot->idname = "WM_OT_circle_gesture";
460  ot->description = "Enter rotate mode with a circular gesture";
461 
465 
466  /* properties */
468 }
469 #endif
470 
473 /* -------------------------------------------------------------------- */
478 {
479  wmWindow *win = CTX_wm_window(C);
480  PropertyRNA *prop;
481 
483 
484  /* add modal handler */
486 
488 
489  if ((prop = RNA_struct_find_property(op->ptr, "cursor"))) {
491  }
492 
493  return OPERATOR_RUNNING_MODAL;
494 }
495 
497 {
498  wmWindow *win = CTX_wm_window(C);
499  PropertyRNA *prop;
500 
502 
503  /* add modal handler */
505 
507 
508  if ((prop = RNA_struct_find_property(op->ptr, "cursor"))) {
510  }
511 
512  return OPERATOR_RUNNING_MODAL;
513 }
514 
516 {
517  int retval = OPERATOR_FINISHED;
518  wmGesture *gesture = op->customdata;
519  PointerRNA itemptr;
520  float loc[2];
521  int i;
522  const short *lasso = gesture->customdata;
523 
524  /* operator storage as path. */
525 
526  RNA_collection_clear(op->ptr, "path");
527  for (i = 0; i < gesture->points; i++, lasso += 2) {
528  loc[0] = lasso[0];
529  loc[1] = lasso[1];
530  RNA_collection_add(op->ptr, "path", &itemptr);
531  RNA_float_set_array(&itemptr, "loc", loc);
532  }
533 
534  gesture_modal_end(C, op);
535 
536  if (op->type->exec) {
537  retval = op->type->exec(C, op);
538  OPERATOR_RETVAL_CHECK(retval);
539  }
540 
541  return retval;
542 }
543 
545 {
546  wmGesture *gesture = op->customdata;
547 
548  if (event->type == EVT_MODAL_MAP) {
549  switch (event->val) {
550  case GESTURE_MODAL_MOVE: {
551  gesture->move = !gesture->move;
552  break;
553  }
554  }
555  }
556  else {
557  switch (event->type) {
558  case MOUSEMOVE:
559  case INBETWEEN_MOUSEMOVE: {
561 
562  if (gesture->points == gesture->points_alloc) {
563  gesture->points_alloc *= 2;
564  gesture->customdata = MEM_reallocN(gesture->customdata,
565  sizeof(short[2]) * gesture->points_alloc);
566  }
567 
568  {
569  short(*lasso)[2] = gesture->customdata;
570 
571  const int x = ((event->xy[0] - gesture->winrct.xmin) - lasso[gesture->points - 1][0]);
572  const int y = ((event->xy[1] - gesture->winrct.ymin) - lasso[gesture->points - 1][1]);
573 
574  /* move the lasso */
575  if (gesture->move) {
576  for (int i = 0; i < gesture->points; i++) {
577  lasso[i][0] += x;
578  lasso[i][1] += y;
579  }
580  }
581  /* Make a simple distance check to get a smoother lasso
582  * add only when at least 2 pixels between this and previous location. */
583  else if ((x * x + y * y) > pow2f(2.0f * UI_DPI_FAC)) {
584  lasso[gesture->points][0] = event->xy[0] - gesture->winrct.xmin;
585  lasso[gesture->points][1] = event->xy[1] - gesture->winrct.ymin;
586  gesture->points++;
587  }
588  }
589  break;
590  }
591  case LEFTMOUSE:
592  case MIDDLEMOUSE:
593  case RIGHTMOUSE: {
594  if (event->val == KM_RELEASE) { /* key release */
595  return gesture_lasso_apply(C, op);
596  }
597  break;
598  }
599  case EVT_ESCKEY: {
600  gesture_modal_end(C, op);
601  return OPERATOR_CANCELLED;
602  }
603  }
604  }
605 
606  gesture->is_active_prev = gesture->is_active;
607  return OPERATOR_RUNNING_MODAL;
608 }
609 
611 {
612  return WM_gesture_lasso_modal(C, op, event);
613 }
614 
616 {
617  gesture_modal_end(C, op);
618 }
619 
621 {
622  gesture_modal_end(C, op);
623 }
624 
626  wmOperator *op,
627  int *r_mcoords_len))[2]
628 {
629  PropertyRNA *prop = RNA_struct_find_property(op->ptr, "path");
630  int(*mcoords)[2] = NULL;
631  BLI_assert(prop != NULL);
632 
633  if (prop) {
634  const int len = RNA_property_collection_length(op->ptr, prop);
635 
636  if (len) {
637  int i = 0;
638  mcoords = MEM_mallocN(sizeof(int[2]) * len, __func__);
639 
640  RNA_PROP_BEGIN (op->ptr, itemptr, prop) {
641  float loc[2];
642 
643  RNA_float_get_array(&itemptr, "loc", loc);
644  mcoords[i][0] = (int)loc[0];
645  mcoords[i][1] = (int)loc[1];
646  i++;
647  }
648  RNA_PROP_END;
649  }
650  *r_mcoords_len = len;
651  }
652  else {
653  *r_mcoords_len = 0;
654  }
655 
656  /* cast for 'const' */
657  return mcoords;
658 }
659 
660 #if 0
661 /* template to copy from */
662 
663 static int gesture_lasso_exec(bContext *C, wmOperator *op)
664 {
665  RNA_BEGIN (op->ptr, itemptr, "path") {
666  float loc[2];
667 
668  RNA_float_get_array(&itemptr, "loc", loc);
669  printf("Location: %f %f\n", loc[0], loc[1]);
670  }
671  RNA_END;
672 
673  return OPERATOR_FINISHED;
674 }
675 
676 void WM_OT_lasso_gesture(wmOperatorType *ot)
677 {
678  PropertyRNA *prop;
679 
680  ot->name = "Lasso Gesture";
681  ot->idname = "WM_OT_lasso_gesture";
682  ot->description = "Select objects within the lasso as you move the pointer";
683 
686  ot->exec = gesture_lasso_exec;
687 
689 
691 
692  prop = RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
693  RNA_def_property_struct_runtime(ot->srna, prop, &RNA_OperatorMousePath);
694 }
695 #endif
696 
699 /* -------------------------------------------------------------------- */
713 {
714  wmGesture *gesture = op->customdata;
715  rcti *rect = gesture->customdata;
716 
717  if (rect->xmin == rect->xmax && rect->ymin == rect->ymax) {
718  return 0;
719  }
720 
721  /* operator arguments and storage. */
722  RNA_int_set(op->ptr, "xstart", rect->xmin);
723  RNA_int_set(op->ptr, "ystart", rect->ymin);
724  RNA_int_set(op->ptr, "xend", rect->xmax);
725  RNA_int_set(op->ptr, "yend", rect->ymax);
726  RNA_boolean_set(op->ptr, "flip", gesture->use_flip);
727 
728  if (op->type->exec) {
729  int retval = op->type->exec(C, op);
730  OPERATOR_RETVAL_CHECK(retval);
731  }
732 
733  return 1;
734 }
735 
737 {
738  wmWindow *win = CTX_wm_window(C);
739  PropertyRNA *prop;
740 
742 
743  if (WM_event_is_mouse_drag_or_press(event)) {
744  wmGesture *gesture = op->customdata;
745  gesture->is_active = true;
746  }
747 
748  /* add modal handler */
750 
752 
753  if ((prop = RNA_struct_find_property(op->ptr, "cursor"))) {
755  }
756 
757  return OPERATOR_RUNNING_MODAL;
758 }
760 {
761  WM_gesture_straightline_invoke(C, op, event);
762  wmGesture *gesture = op->customdata;
763  gesture->draw_active_side = true;
764  gesture->use_flip = false;
765  return OPERATOR_RUNNING_MODAL;
766 }
767 
768 #define STRAIGHTLINE_SNAP_DEG 15.0f
770 {
771  const float line_start[2] = {rect->xmin, rect->ymin};
772  const float line_end[2] = {rect->xmax, rect->ymax};
773  const float x_axis[2] = {1.0f, 0.0f};
774 
775  float line_direction[2];
776  sub_v2_v2v2(line_direction, line_end, line_start);
777  const float line_length = normalize_v2(line_direction);
778 
779  const float angle = angle_signed_v2v2(x_axis, line_direction);
780  const float angle_deg = RAD2DEG(angle) + (STRAIGHTLINE_SNAP_DEG / 2.0f);
781  const float angle_snapped_deg = -floorf(angle_deg / STRAIGHTLINE_SNAP_DEG) *
783  const float angle_snapped = DEG2RAD(angle_snapped_deg);
784 
785  float line_snapped_end[2];
786  rotate_v2_v2fl(line_snapped_end, x_axis, angle_snapped);
787  mul_v2_fl(line_snapped_end, line_length);
788  add_v2_v2(line_snapped_end, line_start);
789 
790  rect->xmax = (int)line_snapped_end[0];
791  rect->ymax = (int)line_snapped_end[1];
792 }
793 
795 {
796  wmGesture *gesture = op->customdata;
797  wmWindow *win = CTX_wm_window(C);
798  rcti *rect = gesture->customdata;
799 
800  if (event->type == EVT_MODAL_MAP) {
801  switch (event->val) {
802  case GESTURE_MODAL_MOVE: {
803  gesture->move = !gesture->move;
804  break;
805  }
806  case GESTURE_MODAL_BEGIN: {
807  if (gesture->is_active == false) {
808  gesture->is_active = true;
810  }
811  break;
812  }
813  case GESTURE_MODAL_SNAP: {
814  /* Toggle snapping on/off. */
815  gesture->use_snap = !gesture->use_snap;
816  break;
817  }
818  case GESTURE_MODAL_FLIP: {
819  /* Toggle flipping on/off. */
820  gesture->use_flip = !gesture->use_flip;
823  break;
824  }
825  case GESTURE_MODAL_SELECT: {
826  if (gesture_straightline_apply(C, op)) {
827  gesture_modal_end(C, op);
828  return OPERATOR_FINISHED;
829  }
830  gesture_modal_end(C, op);
831  return OPERATOR_CANCELLED;
832  }
833  case GESTURE_MODAL_CANCEL: {
834  gesture_modal_end(C, op);
835  return OPERATOR_CANCELLED;
836  }
837  }
838  }
839  else {
840  switch (event->type) {
841  case MOUSEMOVE: {
842  if (gesture->is_active == false) {
843  rect->xmin = rect->xmax = event->xy[0] - gesture->winrct.xmin;
844  rect->ymin = rect->ymax = event->xy[1] - gesture->winrct.ymin;
845  }
846  else if (gesture->move) {
847  BLI_rcti_translate(rect,
848  (event->xy[0] - gesture->winrct.xmin) - rect->xmax,
849  (event->xy[1] - gesture->winrct.ymin) - rect->ymax);
851  }
852  else {
853  rect->xmax = event->xy[0] - gesture->winrct.xmin;
854  rect->ymax = event->xy[1] - gesture->winrct.ymin;
856  }
857 
858  if (gesture->use_snap) {
861  }
862 
864 
865  break;
866  }
867  }
868  }
869 
870  gesture->is_active_prev = gesture->is_active;
871  return OPERATOR_RUNNING_MODAL;
872 }
873 
875 {
876  wmGesture *gesture = op->customdata;
877  wmWindow *win = CTX_wm_window(C);
878  rcti *rect = gesture->customdata;
879 
880  if (event->type == EVT_MODAL_MAP) {
881  switch (event->val) {
882  case GESTURE_MODAL_MOVE: {
883  gesture->move = !gesture->move;
884  break;
885  }
886  case GESTURE_MODAL_BEGIN: {
887  if (gesture->is_active == false) {
888  gesture->is_active = true;
890  }
891  break;
892  }
893  case GESTURE_MODAL_SNAP: {
894  /* Toggle snapping on/off. */
895  gesture->use_snap = !gesture->use_snap;
896  break;
897  }
898  case GESTURE_MODAL_FLIP: {
899  /* Toggle flip on/off. */
900  gesture->use_flip = !gesture->use_flip;
902  break;
903  }
906  case GESTURE_MODAL_IN:
907  case GESTURE_MODAL_OUT: {
908  if (gesture->wait_for_input) {
909  gesture->modal_state = event->val;
910  }
911  if (gesture_straightline_apply(C, op)) {
912  gesture_modal_end(C, op);
913  return OPERATOR_FINISHED;
914  }
915  gesture_modal_end(C, op);
916  return OPERATOR_CANCELLED;
917  }
918  case GESTURE_MODAL_CANCEL: {
919  gesture_modal_end(C, op);
920  return OPERATOR_CANCELLED;
921  }
922  }
923  }
924  else {
925  switch (event->type) {
926  case MOUSEMOVE: {
927  if (gesture->is_active == false) {
928  rect->xmin = rect->xmax = event->xy[0] - gesture->winrct.xmin;
929  rect->ymin = rect->ymax = event->xy[1] - gesture->winrct.ymin;
930  }
931  else if (gesture->move) {
932  BLI_rcti_translate(rect,
933  (event->xy[0] - gesture->winrct.xmin) - rect->xmax,
934  (event->xy[1] - gesture->winrct.ymin) - rect->ymax);
935  }
936  else {
937  rect->xmax = event->xy[0] - gesture->winrct.xmin;
938  rect->ymax = event->xy[1] - gesture->winrct.ymin;
939  }
940 
941  if (gesture->use_snap) {
943  }
944 
946 
947  break;
948  }
949  }
950  }
951 
952  gesture->is_active_prev = gesture->is_active;
953  return OPERATOR_RUNNING_MODAL;
954 }
955 
957 {
958  gesture_modal_end(C, op);
959 }
960 
961 #if 0
962 /* template to copy from */
963 void WM_OT_straightline_gesture(wmOperatorType *ot)
964 {
965  PropertyRNA *prop;
966 
967  ot->name = "Straight Line Gesture";
968  ot->idname = "WM_OT_straightline_gesture";
969  ot->description = "Draw a straight line as you move the pointer";
970 
973  ot->exec = gesture_straightline_exec;
974 
976 
978 }
979 #endif
980 
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:738
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:749
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:723
#define BLI_assert(a)
Definition: BLI_assert.h:46
MINLINE int min_ii(int a, int b)
MINLINE float pow2f(float x)
MINLINE int max_ii(int a, int b)
#define DEG2RAD(_deg)
#define RAD2DEG(_rad)
MINLINE void mul_v2_fl(float r[2], float f)
MINLINE void add_v2_v2(float r[2], const float a[2])
float angle_signed_v2v2(const float v1[2], const float v2[2]) ATTR_WARN_UNUSED_RESULT
Definition: math_vector.c:439
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
void rotate_v2_v2fl(float r[2], const float p[2], float angle)
Definition: math_vector.c:765
MINLINE float normalize_v2(float r[2])
void BLI_rcti_translate(struct rcti *rect, int x, int y)
Definition: rct.c:559
#define UNUSED_FUNCTION(x)
#define UNUSED(x)
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
#define OPERATOR_RETVAL_CHECK(ret)
void ED_area_tag_redraw(ScrArea *area)
Definition: area.c:729
@ SEL_OP_ADD
@ SEL_OP_SUB
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
Read Guarded memory(de)allocation.
#define MEM_reallocN(vmemh, len)
#define RNA_PROP_END
Definition: RNA_access.h:563
#define RNA_BEGIN(sptr, itemptr, propname)
Definition: RNA_access.h:543
#define RNA_END
Definition: RNA_access.h:550
#define RNA_PROP_BEGIN(sptr, itemptr, prop)
Definition: RNA_access.h:556
@ PROP_COLLECTION
Definition: RNA_types.h:65
@ PROP_NONE
Definition: RNA_types.h:126
#define C
Definition: RandGen.cpp:25
#define UI_DPI_FAC
Definition: UI_interface.h:305
@ KM_RELEASE
Definition: WM_types.h:268
@ OPTYPE_DEPENDS_ON_CURSOR
Definition: WM_types.h:184
#define WM_GESTURE_RECT
Definition: WM_types.h:537
#define WM_GESTURE_STRAIGHTLINE
Definition: WM_types.h:541
#define WM_GESTURE_LINES
Definition: WM_types.h:536
#define WM_GESTURE_LASSO
Definition: WM_types.h:539
#define WM_GESTURE_CIRCLE
Definition: WM_types.h:540
#define WM_GESTURE_CROSS_RECT
Definition: WM_types.h:538
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
int len
Definition: draw_manager.c:108
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
ccl_device_inline float3 ceil(const float3 &a)
Definition: math_float3.h:363
#define floorf(x)
Definition: metal/compat.h:224
T floor(const T &a)
void RNA_collection_clear(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5227
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
Definition: rna_access.c:4874
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:5271
void RNA_int_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:4921
void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value)
Definition: rna_access.c:3421
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:717
void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values)
Definition: rna_access.c:4980
bool RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2153
int RNA_property_int_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2429
void RNA_collection_add(PointerRNA *ptr, const char *name, PointerRNA *r_value)
Definition: rna_access.c:5215
int RNA_int_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4910
void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, bool value)
Definition: rna_access.c:2180
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:3402
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
void RNA_float_set_array(PointerRNA *ptr, const char *name, const float *values)
Definition: rna_access.c:4992
int RNA_property_collection_length(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:3762
void RNA_def_property_struct_runtime(StructOrFunctionRNA *cont, PropertyRNA *prop, StructRNA *type)
Definition: rna_define.c:1800
PropertyRNA * RNA_def_property(StructOrFunctionRNA *cont_, const char *identifier, int type, int subtype)
Definition: rna_define.c:1257
int ymin
Definition: DNA_vec_types.h:64
int ymax
Definition: DNA_vec_types.h:64
int xmin
Definition: DNA_vec_types.h:63
int xmax
Definition: DNA_vec_types.h:63
short val
Definition: WM_types.h:680
int xy[2]
Definition: WM_types.h:682
short type
Definition: WM_types.h:678
uint wait_for_input
Definition: WM_types.h:575
uint use_snap
Definition: WM_types.h:580
uint is_active_prev
Definition: WM_types.h:573
int modal_state
Definition: WM_types.h:562
void * customdata
Definition: WM_types.h:592
int points_alloc
Definition: WM_types.h:561
uint move
Definition: WM_types.h:577
int type
Definition: WM_types.h:555
bool draw_active_side
Definition: WM_types.h:564
uint use_flip
Definition: WM_types.h:583
uint is_active
Definition: WM_types.h:571
rcti winrct
Definition: WM_types.h:557
int points
Definition: WM_types.h:559
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:919
const char * name
Definition: WM_types.h:888
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:935
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
struct wmOperatorType * type
struct PointerRNA * ptr
void WM_cursor_modal_set(wmWindow *win, int val)
Definition: wm_cursors.c:191
void WM_cursor_modal_restore(wmWindow *win)
Definition: wm_cursors.c:200
bool WM_event_is_mouse_drag_or_press(const wmEvent *event)
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
@ RIGHTMOUSE
@ EVT_MODAL_MAP
@ MOUSEMOVE
@ LEFTMOUSE
@ NDOF_MOTION
@ MIDDLEMOUSE
@ EVT_ESCKEY
@ INBETWEEN_MOUSEMOVE
@ GESTURE_MODAL_CIRCLE_SIZE
@ GESTURE_MODAL_OUT
@ GESTURE_MODAL_SNAP
@ GESTURE_MODAL_CIRCLE_ADD
@ GESTURE_MODAL_CANCEL
@ GESTURE_MODAL_CIRCLE_SUB
@ GESTURE_MODAL_MOVE
@ GESTURE_MODAL_NOP
@ GESTURE_MODAL_DESELECT
@ GESTURE_MODAL_CONFIRM
@ GESTURE_MODAL_IN
@ GESTURE_MODAL_FLIP
@ GESTURE_MODAL_BEGIN
@ GESTURE_MODAL_SELECT
wmOperatorType * ot
Definition: wm_files.c:3479
wmGesture * WM_gesture_new(wmWindow *window, const ARegion *region, const wmEvent *event, int type)
Definition: wm_gesture.c:37
void wm_gesture_tag_redraw(wmWindow *win)
Definition: wm_gesture.c:468
void WM_gesture_end(wmWindow *win, wmGesture *gesture)
Definition: wm_gesture.c:86
void WM_gesture_box_cancel(bContext *C, wmOperator *op)
int WM_gesture_straightline_invoke(bContext *C, wmOperator *op, const wmEvent *event)
#define STRAIGHTLINE_SNAP_DEG
static bool gesture_box_apply(bContext *C, wmOperator *op)
int WM_gesture_box_invoke(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_circle_invoke(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_lines_modal(bContext *C, wmOperator *op, const wmEvent *event)
static void gesture_modal_end(bContext *C, wmOperator *op)
static int UNUSED_FUNCTION() gesture_modal_state_from_operator(wmOperator *op)
void WM_gesture_straightline_cancel(bContext *C, wmOperator *op)
void WM_gesture_lines_cancel(bContext *C, wmOperator *op)
int WM_gesture_straightline_modal(bContext *C, wmOperator *op, const wmEvent *event)
static bool gesture_straightline_apply(bContext *C, wmOperator *op)
void WM_gesture_circle_cancel(bContext *C, wmOperator *op)
static void gesture_circle_apply(bContext *C, wmOperator *op)
int WM_gesture_box_modal(bContext *C, wmOperator *op, const wmEvent *event)
static bool gesture_box_apply_rect(wmOperator *op)
int WM_gesture_circle_modal(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_lasso_modal(bContext *C, wmOperator *op, const wmEvent *event)
void WM_gesture_lasso_cancel(bContext *C, wmOperator *op)
int WM_gesture_lasso_invoke(bContext *C, wmOperator *op, const wmEvent *event)
const int(* WM_gesture_lasso_path_to_array(bContext *UNUSED(C), wmOperator *op, int *r_mcoords_len))[2]
static void gesture_modal_state_to_operator(wmOperator *op, int modal_state)
static int gesture_lasso_apply(bContext *C, wmOperator *op)
int WM_gesture_lines_invoke(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_straightline_oneshot_modal(bContext *C, wmOperator *op, const wmEvent *event)
static void wm_gesture_straightline_do_angle_snap(rcti *rect)
int WM_gesture_straightline_active_side_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void WM_operator_properties_gesture_straightline(wmOperatorType *ot, int cursor)
void WM_operator_properties_gesture_circle(wmOperatorType *ot)
bool WM_operator_winactive(bContext *C)