Blender  V2.93
wm_event_query.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2007 Blender Foundation.
17  * All rights reserved.
18  */
19 
26 #include <stdlib.h>
27 #include <string.h>
28 
29 #include "DNA_listBase.h"
30 #include "DNA_scene_types.h"
31 #include "DNA_screen_types.h"
32 #include "DNA_userdef_types.h"
34 
35 #include "BLI_blenlib.h"
36 #include "BLI_math.h"
37 #include "BLI_utildefines.h"
38 
39 #include "BKE_context.h"
40 
41 #include "RNA_access.h"
42 
43 #include "WM_api.h"
44 #include "WM_types.h"
45 
46 #include "wm_event_system.h"
47 #include "wm_event_types.h"
48 
49 #include "RNA_enum_types.h"
50 
51 #include "DEG_depsgraph.h"
52 
53 /* -------------------------------------------------------------------- */
57 static void event_ids_from_type_and_value(const short type,
58  const short val,
59  const char **r_type_id,
60  const char **r_val_id)
61 {
62  /* Type. */
64 
65  /* Value. */
66  if (ISTWEAK(type)) {
68  }
69  else {
71  }
72 }
73 
74 /* for debugging only, getting inspecting events manually is tedious */
75 void WM_event_print(const wmEvent *event)
76 {
77  if (event) {
78  const char *unknown = "UNKNOWN";
79  const char *type_id = unknown;
80  const char *val_id = unknown;
81  const char *prev_type_id = unknown;
82  const char *prev_val_id = unknown;
83 
84  event_ids_from_type_and_value(event->type, event->val, &type_id, &val_id);
85  event_ids_from_type_and_value(event->prevtype, event->prevval, &prev_type_id, &prev_val_id);
86 
87  printf(
88  "wmEvent type:%d / %s, val:%d / %s,\n"
89  " prev_type:%d / %s, prev_val:%d / %s,\n"
90  " shift:%d, ctrl:%d, alt:%d, oskey:%d, keymodifier:%d, is_repeat:%d,\n"
91  " mouse:(%d,%d), ascii:'%c', utf8:'%.*s', pointer:%p\n",
92  event->type,
93  type_id,
94  event->val,
95  val_id,
96  event->prevtype,
97  prev_type_id,
98  event->prevval,
99  prev_val_id,
100  event->shift,
101  event->ctrl,
102  event->alt,
103  event->oskey,
104  event->keymodifier,
105  event->is_repeat,
106  event->x,
107  event->y,
108  event->ascii,
109  BLI_str_utf8_size(event->utf8_buf),
110  event->utf8_buf,
111  (const void *)event);
112 
113 #ifdef WITH_INPUT_NDOF
114  if (ISNDOF(event->type)) {
115  const wmNDOFMotionData *ndof = event->customdata;
116  if (event->type == NDOF_MOTION) {
117  printf(" ndof: rot: (%.4f %.4f %.4f), tx: (%.4f %.4f %.4f), dt: %.4f, progress: %u\n",
118  UNPACK3(ndof->rvec),
119  UNPACK3(ndof->tvec),
120  ndof->dt,
121  ndof->progress);
122  }
123  else {
124  /* ndof buttons printed already */
125  }
126  }
127 #endif /* WITH_INPUT_NDOF */
128 
129  if (event->tablet.active != EVT_TABLET_NONE) {
130  const wmTabletData *wmtab = &event->tablet;
131  printf(" tablet: active: %d, pressure %.4f, tilt: (%.4f %.4f)\n",
132  wmtab->active,
133  wmtab->pressure,
134  wmtab->x_tilt,
135  wmtab->y_tilt);
136  }
137  }
138  else {
139  printf("wmEvent - NULL\n");
140  }
141 }
142 
145 /* -------------------------------------------------------------------- */
150 {
151  int flag = 0;
152  if (event->ctrl) {
153  flag |= KM_CTRL;
154  }
155  if (event->alt) {
156  flag |= KM_ALT;
157  }
158  if (event->shift) {
159  flag |= KM_SHIFT;
160  }
161  if (event->oskey) {
162  flag |= KM_OSKEY;
163  }
164  return flag;
165 }
166 
167 bool WM_event_type_mask_test(const int event_type, const enum eEventType_Mask mask)
168 {
169  /* Keyboard. */
171  if (ISKEYBOARD(event_type)) {
172  return true;
173  }
174  }
176  if (ISKEYMODIFIER(event_type)) {
177  return true;
178  }
179  }
180 
181  /* Mouse. */
182  if (mask & EVT_TYPE_MASK_MOUSE) {
183  if (ISMOUSE(event_type)) {
184  return true;
185  }
186  }
187  else if (mask & EVT_TYPE_MASK_MOUSE_WHEEL) {
188  if (ISMOUSE_WHEEL(event_type)) {
189  return true;
190  }
191  }
192  else if (mask & EVT_TYPE_MASK_MOUSE_GESTURE) {
193  if (ISMOUSE_GESTURE(event_type)) {
194  return true;
195  }
196  }
197 
198  /* Tweak. */
199  if (mask & EVT_TYPE_MASK_TWEAK) {
200  if (ISTWEAK(event_type)) {
201  return true;
202  }
203  }
204 
205  /* Action Zone. */
207  if (IS_EVENT_ACTIONZONE(event_type)) {
208  return true;
209  }
210  }
211 
212  return false;
213 }
214 
217 /* -------------------------------------------------------------------- */
221 /* for modal callbacks, check configuration for how to interpret exit with tweaks */
222 bool WM_event_is_modal_tweak_exit(const wmEvent *event, int tweak_event)
223 {
224  /* if the release-confirm userpref setting is enabled,
225  * tweak events can be canceled when mouse is released
226  */
227  if (U.flag & USER_RELEASECONFIRM) {
228  /* option on, so can exit with km-release */
229  if (event->val == KM_RELEASE) {
230  switch (tweak_event) {
231  case EVT_TWEAK_L:
232  case EVT_TWEAK_M:
233  case EVT_TWEAK_R:
234  return 1;
235  }
236  }
237  else {
238  /* if the initial event wasn't a tweak event then
239  * ignore USER_RELEASECONFIRM setting: see T26756. */
240  if (ELEM(tweak_event, EVT_TWEAK_L, EVT_TWEAK_M, EVT_TWEAK_R) == 0) {
241  return 1;
242  }
243  }
244  }
245  else {
246  /* this is fine as long as not doing km-release, otherwise
247  * some items (i.e. markers) being tweaked may end up getting
248  * dropped all over
249  */
250  if (event->val != KM_RELEASE) {
251  return 1;
252  }
253  }
254 
255  return 0;
256 }
257 
259 {
260  while ((event = event->next)) {
261  if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
262  return false;
263  }
264  }
265  return true;
266 }
267 
268 bool WM_event_is_mouse_drag(const wmEvent *event)
269 {
270  return ISTWEAK(event->type) || (ISMOUSE_BUTTON(event->type) && (event->val == KM_CLICK_DRAG));
271 }
272 
275 /* -------------------------------------------------------------------- */
282 int WM_event_drag_threshold(const struct wmEvent *event)
283 {
284  int drag_threshold;
285  if (WM_event_is_tablet(event)) {
286  drag_threshold = U.drag_threshold_tablet;
287  }
288  else if (ISMOUSE(event->prevtype)) {
289  BLI_assert(event->prevtype != MOUSEMOVE);
290  /* Using the previous type is important is we want to check the last pressed/released button,
291  * The `event->type` would include #MOUSEMOVE which is always the case when dragging
292  * and does not help us know which threshold to use. */
293  drag_threshold = U.drag_threshold_mouse;
294  }
295  else {
296  /* Typically keyboard, could be NDOF button or other less common types. */
297  drag_threshold = U.drag_threshold;
298  }
299  return drag_threshold * U.dpi_fac;
300 }
301 
302 bool WM_event_drag_test_with_delta(const wmEvent *event, const int drag_delta[2])
303 {
304  const int drag_threshold = WM_event_drag_threshold(event);
305  return abs(drag_delta[0]) > drag_threshold || abs(drag_delta[1]) > drag_threshold;
306 }
307 
308 bool WM_event_drag_test(const wmEvent *event, const int prev_xy[2])
309 {
310  const int drag_delta[2] = {
311  prev_xy[0] - event->x,
312  prev_xy[1] - event->y,
313  };
314  return WM_event_drag_test_with_delta(event, drag_delta);
315 }
316 
319 /* -------------------------------------------------------------------- */
323 int WM_userdef_event_map(int kmitype)
324 {
325  switch (kmitype) {
326  case WHEELOUTMOUSE:
327  return (U.uiflag & USER_WHEELZOOMDIR) ? WHEELUPMOUSE : WHEELDOWNMOUSE;
328  case WHEELINMOUSE:
329  return (U.uiflag & USER_WHEELZOOMDIR) ? WHEELDOWNMOUSE : WHEELUPMOUSE;
330  }
331 
332  return kmitype;
333 }
334 
341 {
342  switch (kmitype) {
343  case EVT_TWEAK_L:
344  return LEFTMOUSE;
345  case EVT_TWEAK_M:
346  return MIDDLEMOUSE;
347  case EVT_TWEAK_R:
348  return RIGHTMOUSE;
349  case WHEELOUTMOUSE:
350  return (U.uiflag & USER_WHEELZOOMDIR) ? WHEELUPMOUSE : WHEELDOWNMOUSE;
351  case WHEELINMOUSE:
352  return (U.uiflag & USER_WHEELZOOMDIR) ? WHEELDOWNMOUSE : WHEELUPMOUSE;
353  }
354 
355  return kmitype;
356 }
357 
360 /* -------------------------------------------------------------------- */
364 #ifdef WITH_INPUT_NDOF
365 
366 void WM_event_ndof_pan_get(const wmNDOFMotionData *ndof, float r_pan[3], const bool use_zoom)
367 {
368  int z_flag = use_zoom ? NDOF_ZOOM_INVERT : NDOF_PANZ_INVERT_AXIS;
369  r_pan[0] = ndof->tvec[0] * ((U.ndof_flag & NDOF_PANX_INVERT_AXIS) ? -1.0f : 1.0f);
370  r_pan[1] = ndof->tvec[1] * ((U.ndof_flag & NDOF_PANY_INVERT_AXIS) ? -1.0f : 1.0f);
371  r_pan[2] = ndof->tvec[2] * ((U.ndof_flag & z_flag) ? -1.0f : 1.0f);
372 }
373 
374 void WM_event_ndof_rotate_get(const wmNDOFMotionData *ndof, float r_rot[3])
375 {
376  r_rot[0] = ndof->rvec[0] * ((U.ndof_flag & NDOF_ROTX_INVERT_AXIS) ? -1.0f : 1.0f);
377  r_rot[1] = ndof->rvec[1] * ((U.ndof_flag & NDOF_ROTY_INVERT_AXIS) ? -1.0f : 1.0f);
378  r_rot[2] = ndof->rvec[2] * ((U.ndof_flag & NDOF_ROTZ_INVERT_AXIS) ? -1.0f : 1.0f);
379 }
380 
381 float WM_event_ndof_to_axis_angle(const struct wmNDOFMotionData *ndof, float axis[3])
382 {
383  float angle;
384  angle = normalize_v3_v3(axis, ndof->rvec);
385 
386  axis[0] = axis[0] * ((U.ndof_flag & NDOF_ROTX_INVERT_AXIS) ? -1.0f : 1.0f);
387  axis[1] = axis[1] * ((U.ndof_flag & NDOF_ROTY_INVERT_AXIS) ? -1.0f : 1.0f);
388  axis[2] = axis[2] * ((U.ndof_flag & NDOF_ROTZ_INVERT_AXIS) ? -1.0f : 1.0f);
389 
390  return ndof->dt * angle;
391 }
392 
393 void WM_event_ndof_to_quat(const struct wmNDOFMotionData *ndof, float q[4])
394 {
395  float axis[3];
396  float angle;
397 
398  angle = WM_event_ndof_to_axis_angle(ndof, axis);
399  axis_angle_to_quat(q, axis, angle);
400 }
401 #endif /* WITH_INPUT_NDOF */
402 
405 /* -------------------------------------------------------------------- */
409 /* applies the global tablet pressure correction curve */
410 float wm_pressure_curve(float pressure)
411 {
412  if (U.pressure_threshold_max != 0.0f) {
413  pressure /= U.pressure_threshold_max;
414  }
415 
416  CLAMP(pressure, 0.0f, 1.0f);
417 
418  if (U.pressure_softness != 0.0f) {
419  pressure = powf(pressure, powf(4.0f, -U.pressure_softness));
420  }
421 
422  return pressure;
423 }
424 
425 /* if this is a tablet event, return tablet pressure and set *pen_flip
426  * to 1 if the eraser tool is being used, 0 otherwise */
427 float WM_event_tablet_data(const wmEvent *event, int *pen_flip, float tilt[2])
428 {
429  if (tilt) {
430  tilt[0] = event->tablet.x_tilt;
431  tilt[1] = event->tablet.y_tilt;
432  }
433 
434  if (pen_flip) {
435  (*pen_flip) = (event->tablet.active == EVT_TABLET_ERASER);
436  }
437 
438  return event->tablet.pressure;
439 }
440 
441 bool WM_event_is_tablet(const struct wmEvent *event)
442 {
443  return (event->tablet.active != EVT_TABLET_NONE);
444 }
445 
448 /* -------------------------------------------------------------------- */
456 int WM_event_absolute_delta_x(const struct wmEvent *event)
457 {
458  int dx = event->x - event->prevx;
459 
460  if (!event->is_direction_inverted) {
461  dx = -dx;
462  }
463 
464  return dx;
465 }
466 
467 int WM_event_absolute_delta_y(const struct wmEvent *event)
468 {
469  int dy = event->y - event->prevy;
470 
471  if (!event->is_direction_inverted) {
472  dy = -dy;
473  }
474 
475  return dy;
476 }
477 
480 /* -------------------------------------------------------------------- */
484 #ifdef WITH_INPUT_IME
485 /* most os using ctrl/oskey + space to switch ime, avoid added space */
486 bool WM_event_is_ime_switch(const struct wmEvent *event)
487 {
488  return event->val == KM_PRESS && event->type == EVT_SPACEKEY &&
489  (event->ctrl || event->oskey || event->alt);
490 }
491 #endif
492 
#define BLI_assert(a)
Definition: BLI_assert.h:58
void axis_angle_to_quat(float r[4], const float axis[3], const float angle)
MINLINE float normalize_v3_v3(float r[3], const float a[3])
int BLI_str_utf8_size(const char *p) ATTR_NONNULL()
Definition: string_utf8.c:495
#define UNPACK3(a)
#define ELEM(...)
These structs are the foundation for all linked lists in the library system.
@ USER_WHEELZOOMDIR
@ USER_RELEASECONFIRM
@ NDOF_ROTX_INVERT_AXIS
@ NDOF_ZOOM_INVERT
@ NDOF_PANX_INVERT_AXIS
@ NDOF_PANY_INVERT_AXIS
@ NDOF_ROTY_INVERT_AXIS
@ NDOF_PANZ_INVERT_AXIS
@ NDOF_ROTZ_INVERT_AXIS
_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 type
Group RGB to Bright Vector Camera CLAMP
#define KM_SHIFT
Definition: WM_types.h:221
#define KM_CLICK_DRAG
Definition: WM_types.h:246
#define KM_PRESS
Definition: WM_types.h:242
#define KM_CTRL
Definition: WM_types.h:222
#define KM_ALT
Definition: WM_types.h:223
#define KM_OSKEY
Definition: WM_types.h:224
#define KM_RELEASE
Definition: WM_types.h:243
unsigned int U
Definition: btGjkEpa3.h:78
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
#define powf(x, y)
bool RNA_enum_identifier(const EnumPropertyItem *item, const int value, const char **r_identifier)
Definition: rna_access.c:1830
const EnumPropertyItem rna_enum_event_value_all_items[]
Definition: rna_wm.c:376
const EnumPropertyItem rna_enum_event_value_tweak_items[]
Definition: rna_wm.c:407
const EnumPropertyItem rna_enum_event_type_items[]
Definition: rna_wm.c:146
int y
Definition: WM_types.h:581
short shift
Definition: WM_types.h:618
short ctrl
Definition: WM_types.h:618
short val
Definition: WM_types.h:579
struct wmEvent * next
Definition: WM_types.h:574
char is_direction_inverted
Definition: WM_types.h:638
short oskey
Definition: WM_types.h:618
char utf8_buf[6]
Definition: WM_types.h:589
short keymodifier
Definition: WM_types.h:620
short prevtype
Definition: WM_types.h:602
wmTabletData tablet
Definition: WM_types.h:623
int x
Definition: WM_types.h:581
short prevval
Definition: WM_types.h:604
short alt
Definition: WM_types.h:618
short type
Definition: WM_types.h:577
char ascii
Definition: WM_types.h:591
char is_repeat
Definition: WM_types.h:599
float pressure
Definition: WM_types.h:541
float x_tilt
Definition: WM_types.h:543
float y_tilt
Definition: WM_types.h:545
__forceinline const avxi abs(const avxi &a)
Definition: util_avxi.h:186
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
bool WM_event_is_tablet(const struct wmEvent *event)
bool WM_event_drag_test_with_delta(const wmEvent *event, const int drag_delta[2])
int WM_event_drag_threshold(const struct wmEvent *event)
void WM_event_print(const wmEvent *event)
bool WM_event_drag_test(const wmEvent *event, const int prev_xy[2])
int WM_userdef_event_map(int kmitype)
float wm_pressure_curve(float pressure)
float WM_event_tablet_data(const wmEvent *event, int *pen_flip, float tilt[2])
bool WM_event_is_mouse_drag(const wmEvent *event)
bool WM_event_is_modal_tweak_exit(const wmEvent *event, int tweak_event)
int WM_event_absolute_delta_y(const struct wmEvent *event)
bool WM_event_type_mask_test(const int event_type, const enum eEventType_Mask mask)
bool WM_event_is_last_mousemove(const wmEvent *event)
static void event_ids_from_type_and_value(const short type, const short val, const char **r_type_id, const char **r_val_id)
int WM_userdef_event_type_from_keymap_type(int kmitype)
int WM_event_absolute_delta_x(const struct wmEvent *event)
int WM_event_modifier_flag(const wmEvent *event)
#define ISMOUSE_BUTTON(event_type)
#define ISTWEAK(event_type)
@ EVT_TABLET_NONE
@ EVT_TABLET_ERASER
@ RIGHTMOUSE
@ WHEELUPMOUSE
@ EVT_TWEAK_M
@ EVT_SPACEKEY
@ WHEELDOWNMOUSE
@ MOUSEMOVE
@ EVT_TWEAK_R
@ LEFTMOUSE
@ NDOF_MOTION
@ MIDDLEMOUSE
@ WHEELOUTMOUSE
@ EVT_TWEAK_L
@ WHEELINMOUSE
@ INBETWEEN_MOUSEMOVE
#define ISMOUSE_WHEEL(event_type)
eEventType_Mask
@ EVT_TYPE_MASK_TWEAK
@ EVT_TYPE_MASK_ACTIONZONE
@ EVT_TYPE_MASK_KEYBOARD_MODIFIER
@ EVT_TYPE_MASK_MOUSE_WHEEL
@ EVT_TYPE_MASK_MOUSE_GESTURE
@ EVT_TYPE_MASK_MOUSE
@ EVT_TYPE_MASK_KEYBOARD
#define ISKEYMODIFIER(event_type)
#define IS_EVENT_ACTIONZONE(event_type)
#define ISMOUSE_GESTURE(event_type)
#define ISKEYBOARD(event_type)
#define ISNDOF(event_type)
#define ISMOUSE(event_type)