2023-08-16 00:20:26 +10:00
|
|
|
/* SPDX-FileCopyrightText: 2007 Blender Authors
|
2023-05-31 16:19:06 +02:00
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
2020-01-10 17:27:53 +11:00
|
|
|
|
|
|
|
|
/** \file
|
|
|
|
|
* \ingroup wm
|
|
|
|
|
*
|
|
|
|
|
* Read-only queries utility functions for the event system.
|
|
|
|
|
*/
|
|
|
|
|
|
2023-07-21 16:05:33 +10:00
|
|
|
#include <cstdlib>
|
|
|
|
|
#include <cstring>
|
2020-01-10 17:27:53 +11:00
|
|
|
|
|
|
|
|
#include "DNA_listBase.h"
|
|
|
|
|
#include "DNA_scene_types.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "DNA_screen_types.h"
|
2020-01-10 17:27:53 +11:00
|
|
|
#include "DNA_userdef_types.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "DNA_windowmanager_types.h"
|
2020-01-10 17:27:53 +11:00
|
|
|
|
|
|
|
|
#include "BLI_blenlib.h"
|
Cleanup: reduce amount of math-related includes
Using ClangBuildAnalyzer on the whole Blender build, it was pointing
out that BLI_math.h is the heaviest "header hub" (i.e. non tiny file
that is included a lot).
However, there's very little (actually zero) source files in Blender
that need "all the math" (base, colors, vectors, matrices,
quaternions, intersection, interpolation, statistics, solvers and
time). A common use case is source files needing just vectors, or
just vectors & matrices, or just colors etc. Actually, 181 files
were including the whole math thing without needing it at all.
This change removes BLI_math.h completely, and instead in all the
places that need it, includes BLI_math_vector.h or BLI_math_color.h
and so on.
Change from that:
- BLI_math_color.h was included 1399 times -> now 408 (took 114.0sec
to parse -> now 36.3sec)
- BLI_simd.h 1403 -> 418 (109.7sec -> 34.9sec).
Full rebuild of Blender (Apple M1, Xcode, RelWithDebInfo) is not
affected much (342sec -> 334sec). Most of benefit would be when
someone's changing BLI_simd.h or BLI_math_color.h or similar files,
that now there's 3x fewer files result in a recompile.
Pull Request #110944
2023-08-09 11:39:20 +03:00
|
|
|
#include "BLI_math_rotation.h"
|
|
|
|
|
#include "BLI_math_vector.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BLI_utildefines.h"
|
2020-01-10 17:27:53 +11:00
|
|
|
|
|
|
|
|
#include "BKE_context.h"
|
|
|
|
|
|
2023-08-10 22:40:27 +02:00
|
|
|
#include "RNA_access.hh"
|
2020-01-10 17:27:53 +11:00
|
|
|
|
2023-08-04 23:11:22 +02:00
|
|
|
#include "WM_api.hh"
|
|
|
|
|
#include "WM_types.hh"
|
2020-01-10 17:27:53 +11:00
|
|
|
|
|
|
|
|
#include "wm_event_system.h"
|
2023-08-04 23:11:22 +02:00
|
|
|
#include "wm_event_types.hh"
|
2020-01-10 17:27:53 +11:00
|
|
|
|
2023-08-10 22:40:27 +02:00
|
|
|
#include "RNA_enum_types.hh"
|
2020-01-10 17:27:53 +11:00
|
|
|
|
2023-09-22 03:18:17 +02:00
|
|
|
#include "DEG_depsgraph.hh"
|
2020-01-10 17:27:53 +11:00
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Event Printing
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2022-03-21 17:15:18 +11:00
|
|
|
struct FlagIdentifierPair {
|
|
|
|
|
const char *id;
|
|
|
|
|
uint flag;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void event_ids_from_flag(char *str,
|
2023-05-07 15:22:58 +10:00
|
|
|
const int str_maxncpy,
|
2023-07-21 10:59:54 +10:00
|
|
|
const FlagIdentifierPair *flag_data,
|
2022-03-21 17:15:18 +11:00
|
|
|
const int flag_data_len,
|
|
|
|
|
const uint flag)
|
|
|
|
|
{
|
|
|
|
|
int ofs = 0;
|
2023-05-07 15:22:58 +10:00
|
|
|
ofs += BLI_strncpy_rlen(str + ofs, "{", str_maxncpy - ofs);
|
2022-03-21 17:15:18 +11:00
|
|
|
for (int i = 0; i < flag_data_len; i++) {
|
|
|
|
|
if (flag & flag_data[i].flag) {
|
|
|
|
|
if (ofs != 1) {
|
2023-05-07 15:22:58 +10:00
|
|
|
ofs += BLI_strncpy_rlen(str + ofs, "|", str_maxncpy - ofs);
|
2022-03-21 17:15:18 +11:00
|
|
|
}
|
2023-05-07 15:22:58 +10:00
|
|
|
ofs += BLI_strncpy_rlen(str + ofs, flag_data[i].id, str_maxncpy - ofs);
|
2022-03-21 17:15:18 +11:00
|
|
|
}
|
|
|
|
|
}
|
2023-05-07 15:22:58 +10:00
|
|
|
ofs += BLI_strncpy_rlen(str + ofs, "}", str_maxncpy - ofs);
|
2022-03-21 17:15:18 +11:00
|
|
|
}
|
|
|
|
|
|
2021-01-13 19:48:54 +11:00
|
|
|
static void event_ids_from_type_and_value(const short type,
|
|
|
|
|
const short val,
|
|
|
|
|
const char **r_type_id,
|
|
|
|
|
const char **r_val_id)
|
|
|
|
|
{
|
|
|
|
|
/* Type. */
|
|
|
|
|
RNA_enum_identifier(rna_enum_event_type_items, type, r_type_id);
|
|
|
|
|
|
|
|
|
|
/* Value. */
|
2022-03-02 15:07:00 +11:00
|
|
|
RNA_enum_identifier(rna_enum_event_value_items, val, r_val_id);
|
2021-01-13 19:48:54 +11:00
|
|
|
}
|
|
|
|
|
|
2020-01-10 17:27:53 +11:00
|
|
|
void WM_event_print(const wmEvent *event)
|
|
|
|
|
{
|
|
|
|
|
if (event) {
|
|
|
|
|
const char *unknown = "UNKNOWN";
|
|
|
|
|
const char *type_id = unknown;
|
|
|
|
|
const char *val_id = unknown;
|
2020-05-14 17:59:14 +10:00
|
|
|
const char *prev_type_id = unknown;
|
|
|
|
|
const char *prev_val_id = unknown;
|
2020-01-10 17:27:53 +11:00
|
|
|
|
2021-01-13 19:48:54 +11:00
|
|
|
event_ids_from_type_and_value(event->type, event->val, &type_id, &val_id);
|
2021-10-21 13:24:17 +11:00
|
|
|
event_ids_from_type_and_value(event->prev_type, event->prev_val, &prev_type_id, &prev_val_id);
|
2020-05-14 17:59:14 +10:00
|
|
|
|
2022-03-21 17:15:18 +11:00
|
|
|
char modifier_id[128];
|
|
|
|
|
{
|
2023-07-21 10:59:54 +10:00
|
|
|
FlagIdentifierPair flag_data[] = {
|
2022-03-21 17:15:18 +11:00
|
|
|
{"SHIFT", KM_SHIFT},
|
|
|
|
|
{"CTRL", KM_CTRL},
|
|
|
|
|
{"ALT", KM_ALT},
|
|
|
|
|
{"OS", KM_OSKEY},
|
|
|
|
|
};
|
|
|
|
|
event_ids_from_flag(
|
|
|
|
|
modifier_id, sizeof(modifier_id), flag_data, ARRAY_SIZE(flag_data), event->modifier);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char flag_id[128];
|
|
|
|
|
{
|
2023-07-21 10:59:54 +10:00
|
|
|
FlagIdentifierPair flag_data[] = {
|
2022-03-21 17:15:18 +11:00
|
|
|
{"SCROLL_INVERT", WM_EVENT_SCROLL_INVERT},
|
|
|
|
|
{"IS_REPEAT", WM_EVENT_IS_REPEAT},
|
2023-03-17 14:40:43 +11:00
|
|
|
{"IS_CONSECUTIVE", WM_EVENT_IS_CONSECUTIVE},
|
2022-03-21 17:15:18 +11:00
|
|
|
{"FORCE_DRAG_THRESHOLD", WM_EVENT_FORCE_DRAG_THRESHOLD},
|
|
|
|
|
};
|
|
|
|
|
event_ids_from_flag(flag_id, sizeof(flag_id), flag_data, ARRAY_SIZE(flag_data), event->flag);
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-10 17:27:53 +11:00
|
|
|
printf(
|
2022-03-21 17:15:18 +11:00
|
|
|
"wmEvent type:%d/%s, val:%d/%s, "
|
|
|
|
|
"prev_type:%d/%s, prev_val:%d/%s, "
|
|
|
|
|
"modifier=%s, keymodifier:%d, flag:%s, "
|
2022-07-14 13:54:26 +10:00
|
|
|
"mouse:(%d,%d), utf8:'%.*s', pointer:%p",
|
2020-01-10 17:27:53 +11:00
|
|
|
event->type,
|
|
|
|
|
type_id,
|
|
|
|
|
event->val,
|
|
|
|
|
val_id,
|
2021-10-21 13:24:17 +11:00
|
|
|
event->prev_type,
|
2020-05-14 17:59:14 +10:00
|
|
|
prev_type_id,
|
2021-10-21 13:24:17 +11:00
|
|
|
event->prev_val,
|
2020-05-14 17:59:14 +10:00
|
|
|
prev_val_id,
|
2022-03-21 17:15:18 +11:00
|
|
|
modifier_id,
|
2020-01-10 17:27:53 +11:00
|
|
|
event->keymodifier,
|
2022-03-21 17:15:18 +11:00
|
|
|
flag_id,
|
2021-10-20 23:45:30 +11:00
|
|
|
event->xy[0],
|
|
|
|
|
event->xy[1],
|
2023-09-18 13:36:17 +10:00
|
|
|
BLI_str_utf8_size_or_error(event->utf8_buf),
|
2020-01-10 17:27:53 +11:00
|
|
|
event->utf8_buf,
|
|
|
|
|
(const void *)event);
|
|
|
|
|
|
|
|
|
|
#ifdef WITH_INPUT_NDOF
|
|
|
|
|
if (ISNDOF(event->type)) {
|
2023-07-20 22:12:29 +02:00
|
|
|
const wmNDOFMotionData *ndof = static_cast<const wmNDOFMotionData *>(event->customdata);
|
2020-01-10 17:27:53 +11:00
|
|
|
if (event->type == NDOF_MOTION) {
|
2023-07-20 22:12:29 +02:00
|
|
|
printf(", ndof: rot: (%.4f %.4f %.4f), tx: (%.4f %.4f %.4f), dt: %.4f, progress: %d",
|
2020-01-10 17:27:53 +11:00
|
|
|
UNPACK3(ndof->rvec),
|
|
|
|
|
UNPACK3(ndof->tvec),
|
|
|
|
|
ndof->dt,
|
|
|
|
|
ndof->progress);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* ndof buttons printed already */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif /* WITH_INPUT_NDOF */
|
|
|
|
|
|
2020-01-10 16:54:17 +01:00
|
|
|
if (event->tablet.active != EVT_TABLET_NONE) {
|
|
|
|
|
const wmTabletData *wmtab = &event->tablet;
|
2022-03-21 17:15:18 +11:00
|
|
|
printf(", tablet: active: %d, pressure %.4f, tilt: (%.4f %.4f)",
|
2020-01-10 16:54:17 +01:00
|
|
|
wmtab->active,
|
|
|
|
|
wmtab->pressure,
|
|
|
|
|
wmtab->x_tilt,
|
|
|
|
|
wmtab->y_tilt);
|
2020-01-10 17:27:53 +11:00
|
|
|
}
|
2022-03-21 17:15:18 +11:00
|
|
|
printf("\n");
|
2020-01-10 17:27:53 +11:00
|
|
|
}
|
|
|
|
|
else {
|
2023-07-20 22:12:29 +02:00
|
|
|
printf("wmEvent - nullptr\n");
|
2020-01-10 17:27:53 +11:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Event Modifier/Type Queries
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
bool WM_event_type_mask_test(const int event_type, const enum eEventType_Mask mask)
|
|
|
|
|
{
|
|
|
|
|
/* Keyboard. */
|
|
|
|
|
if (mask & EVT_TYPE_MASK_KEYBOARD) {
|
|
|
|
|
if (ISKEYBOARD(event_type)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (mask & EVT_TYPE_MASK_KEYBOARD_MODIFIER) {
|
|
|
|
|
if (ISKEYMODIFIER(event_type)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Mouse. */
|
|
|
|
|
if (mask & EVT_TYPE_MASK_MOUSE) {
|
|
|
|
|
if (ISMOUSE(event_type)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (mask & EVT_TYPE_MASK_MOUSE_WHEEL) {
|
|
|
|
|
if (ISMOUSE_WHEEL(event_type)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (mask & EVT_TYPE_MASK_MOUSE_GESTURE) {
|
|
|
|
|
if (ISMOUSE_GESTURE(event_type)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-27 12:45:35 +02:00
|
|
|
/* NDOF */
|
|
|
|
|
if (mask & EVT_TYPE_MASK_NDOF) {
|
|
|
|
|
if (ISNDOF(event_type)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-10 17:27:53 +11:00
|
|
|
/* Action Zone. */
|
|
|
|
|
if (mask & EVT_TYPE_MASK_ACTIONZONE) {
|
|
|
|
|
if (IS_EVENT_ACTIONZONE(event_type)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Event Motion Queries
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2022-03-02 14:44:34 +11:00
|
|
|
bool WM_event_is_modal_drag_exit(const wmEvent *event,
|
|
|
|
|
const short init_event_type,
|
|
|
|
|
const short init_event_val)
|
2020-01-10 17:27:53 +11:00
|
|
|
{
|
2022-03-02 14:44:34 +11:00
|
|
|
/* If the release-confirm preference setting is enabled,
|
|
|
|
|
* drag events can be canceled when mouse is released. */
|
2020-01-10 17:27:53 +11:00
|
|
|
if (U.flag & USER_RELEASECONFIRM) {
|
|
|
|
|
/* option on, so can exit with km-release */
|
|
|
|
|
if (event->val == KM_RELEASE) {
|
2022-03-02 14:44:34 +11:00
|
|
|
if ((init_event_val == KM_CLICK_DRAG) && (event->type == init_event_type)) {
|
2023-07-22 11:36:59 +10:00
|
|
|
return true;
|
2022-03-02 14:44:34 +11:00
|
|
|
}
|
2020-01-10 17:27:53 +11:00
|
|
|
}
|
|
|
|
|
else {
|
2022-03-02 14:44:34 +11:00
|
|
|
/* If the initial event wasn't a drag event then
|
2023-02-12 14:37:16 +11:00
|
|
|
* ignore #USER_RELEASECONFIRM setting: see #26756. */
|
2022-03-02 15:07:00 +11:00
|
|
|
if (init_event_val != KM_CLICK_DRAG) {
|
2023-07-22 11:36:59 +10:00
|
|
|
return true;
|
2020-01-10 17:27:53 +11:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
2022-03-02 14:44:34 +11:00
|
|
|
/* This is fine as long as not doing km-release, otherwise some items (i.e. markers)
|
|
|
|
|
* being tweaked may end up getting dropped all over. */
|
2020-01-10 17:27:53 +11:00
|
|
|
if (event->val != KM_RELEASE) {
|
2023-07-22 11:36:59 +10:00
|
|
|
return true;
|
2020-01-10 17:27:53 +11:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-22 11:36:59 +10:00
|
|
|
return false;
|
2020-01-10 17:27:53 +11:00
|
|
|
}
|
|
|
|
|
|
2021-04-13 21:33:52 +10:00
|
|
|
bool WM_event_is_mouse_drag(const wmEvent *event)
|
|
|
|
|
{
|
2022-03-02 15:07:00 +11:00
|
|
|
return (ISMOUSE_BUTTON(event->type) && (event->val == KM_CLICK_DRAG));
|
2021-04-13 21:33:52 +10:00
|
|
|
}
|
|
|
|
|
|
2021-09-23 22:06:50 +10:00
|
|
|
bool WM_event_is_mouse_drag_or_press(const wmEvent *event)
|
|
|
|
|
{
|
|
|
|
|
return WM_event_is_mouse_drag(event) ||
|
|
|
|
|
(ISMOUSE_BUTTON(event->type) && (event->val == KM_PRESS));
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-02 15:07:00 +11:00
|
|
|
int WM_event_drag_direction(const wmEvent *event)
|
|
|
|
|
{
|
|
|
|
|
const int delta[2] = {
|
2022-03-09 09:01:28 +11:00
|
|
|
event->xy[0] - event->prev_press_xy[0],
|
|
|
|
|
event->xy[1] - event->prev_press_xy[1],
|
2022-03-02 15:07:00 +11:00
|
|
|
};
|
|
|
|
|
|
2023-07-21 10:59:54 +10:00
|
|
|
int theta = round_fl_to_int(4.0f * atan2f(float(delta[1]), float(delta[0])) / float(M_PI));
|
2022-03-02 17:54:06 +11:00
|
|
|
int val = KM_DIRECTION_W;
|
2022-03-02 15:07:00 +11:00
|
|
|
|
|
|
|
|
if (theta == 0) {
|
2022-03-02 17:54:06 +11:00
|
|
|
val = KM_DIRECTION_E;
|
2022-03-02 15:07:00 +11:00
|
|
|
}
|
|
|
|
|
else if (theta == 1) {
|
2022-03-02 17:54:06 +11:00
|
|
|
val = KM_DIRECTION_NE;
|
2022-03-02 15:07:00 +11:00
|
|
|
}
|
|
|
|
|
else if (theta == 2) {
|
2022-03-02 17:54:06 +11:00
|
|
|
val = KM_DIRECTION_N;
|
2022-03-02 15:07:00 +11:00
|
|
|
}
|
|
|
|
|
else if (theta == 3) {
|
2022-03-02 17:54:06 +11:00
|
|
|
val = KM_DIRECTION_NW;
|
2022-03-02 15:07:00 +11:00
|
|
|
}
|
|
|
|
|
else if (theta == -1) {
|
2022-03-02 17:54:06 +11:00
|
|
|
val = KM_DIRECTION_SE;
|
2022-03-02 15:07:00 +11:00
|
|
|
}
|
|
|
|
|
else if (theta == -2) {
|
2022-03-02 17:54:06 +11:00
|
|
|
val = KM_DIRECTION_S;
|
2022-03-02 15:07:00 +11:00
|
|
|
}
|
|
|
|
|
else if (theta == -3) {
|
2022-03-02 17:54:06 +11:00
|
|
|
val = KM_DIRECTION_SW;
|
2022-03-02 15:07:00 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
/* debug */
|
|
|
|
|
if (val == 1) {
|
|
|
|
|
printf("tweak north\n");
|
|
|
|
|
}
|
|
|
|
|
if (val == 2) {
|
|
|
|
|
printf("tweak north-east\n");
|
|
|
|
|
}
|
|
|
|
|
if (val == 3) {
|
|
|
|
|
printf("tweak east\n");
|
|
|
|
|
}
|
|
|
|
|
if (val == 4) {
|
|
|
|
|
printf("tweak south-east\n");
|
|
|
|
|
}
|
|
|
|
|
if (val == 5) {
|
|
|
|
|
printf("tweak south\n");
|
|
|
|
|
}
|
|
|
|
|
if (val == 6) {
|
|
|
|
|
printf("tweak south-west\n");
|
|
|
|
|
}
|
|
|
|
|
if (val == 7) {
|
|
|
|
|
printf("tweak west\n");
|
|
|
|
|
}
|
|
|
|
|
if (val == 8) {
|
|
|
|
|
printf("tweak north-west\n");
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
return val;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-27 19:01:46 +11:00
|
|
|
bool WM_cursor_test_motion_and_update(const int mval[2])
|
|
|
|
|
{
|
|
|
|
|
static int mval_prev[2] = {-1, -1};
|
|
|
|
|
bool use_cycle = (len_manhattan_v2v2_int(mval, mval_prev) <= WM_EVENT_CURSOR_MOTION_THRESHOLD);
|
|
|
|
|
copy_v2_v2_int(mval_prev, mval);
|
|
|
|
|
return !use_cycle;
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-10 17:27:53 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
2023-03-17 14:40:43 +11:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Event Consecutive Checks
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
bool WM_event_consecutive_gesture_test(const wmEvent *event)
|
|
|
|
|
{
|
|
|
|
|
return ISMOUSE_GESTURE(event->type) || (event->type == NDOF_MOTION);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool WM_event_consecutive_gesture_test_break(const wmWindow *win, const wmEvent *event)
|
|
|
|
|
{
|
|
|
|
|
/* Cursor motion breaks the chain. */
|
|
|
|
|
if (ISMOUSE_MOTION(event->type)) {
|
|
|
|
|
/* Mouse motion is checked because the user may navigate to a new area
|
|
|
|
|
* and perform the same gesture - logically it's best to view this as two separate gestures. */
|
|
|
|
|
if (len_manhattan_v2v2_int(event->xy, win->event_queue_consecutive_gesture_xy) >
|
|
|
|
|
WM_EVENT_CURSOR_MOTION_THRESHOLD)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (ISKEYBOARD_OR_BUTTON(event->type)) {
|
|
|
|
|
/* Modifiers are excluded because from a user perspective,
|
|
|
|
|
* releasing a modifier (for e.g.) should not begin a new action. */
|
|
|
|
|
if (!ISKEYMODIFIER(event->type)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (event->type == WINDEACTIVATE) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
2020-01-10 17:27:53 +11:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Event Click/Drag Checks
|
|
|
|
|
*
|
|
|
|
|
* Values under this limit are detected as clicks.
|
|
|
|
|
*
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
int WM_event_drag_threshold(const wmEvent *event)
|
2020-01-10 17:27:53 +11:00
|
|
|
{
|
|
|
|
|
int drag_threshold;
|
2022-07-21 15:54:39 +10:00
|
|
|
BLI_assert(event->prev_press_type != MOUSEMOVE);
|
|
|
|
|
if (ISMOUSE_BUTTON(event->prev_press_type)) {
|
2021-03-02 18:19:13 +11:00
|
|
|
/* Using the previous type is important is we want to check the last pressed/released button,
|
|
|
|
|
* The `event->type` would include #MOUSEMOVE which is always the case when dragging
|
|
|
|
|
* and does not help us know which threshold to use. */
|
2021-06-04 01:15:15 +10:00
|
|
|
if (WM_event_is_tablet(event)) {
|
|
|
|
|
drag_threshold = U.drag_threshold_tablet;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
drag_threshold = U.drag_threshold_mouse;
|
|
|
|
|
}
|
2020-01-10 17:27:53 +11:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* Typically keyboard, could be NDOF button or other less common types. */
|
|
|
|
|
drag_threshold = U.drag_threshold;
|
|
|
|
|
}
|
2023-03-17 04:19:05 +01:00
|
|
|
return drag_threshold * UI_SCALE_FAC;
|
2020-01-10 17:27:53 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool WM_event_drag_test_with_delta(const wmEvent *event, const int drag_delta[2])
|
|
|
|
|
{
|
|
|
|
|
const int drag_threshold = WM_event_drag_threshold(event);
|
|
|
|
|
return abs(drag_delta[0]) > drag_threshold || abs(drag_delta[1]) > drag_threshold;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool WM_event_drag_test(const wmEvent *event, const int prev_xy[2])
|
|
|
|
|
{
|
2021-10-21 15:29:56 -04:00
|
|
|
int drag_delta[2];
|
|
|
|
|
sub_v2_v2v2_int(drag_delta, prev_xy, event->xy);
|
2020-01-10 17:27:53 +11:00
|
|
|
return WM_event_drag_test_with_delta(event, drag_delta);
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-09 08:36:36 +11:00
|
|
|
void WM_event_drag_start_mval(const wmEvent *event, const ARegion *region, int r_mval[2])
|
|
|
|
|
{
|
2022-03-09 09:01:28 +11:00
|
|
|
const int *xy = (event->val == KM_CLICK_DRAG) ? event->prev_press_xy : event->xy;
|
2022-03-09 08:36:36 +11:00
|
|
|
r_mval[0] = xy[0] - region->winrct.xmin;
|
|
|
|
|
r_mval[1] = xy[1] - region->winrct.ymin;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WM_event_drag_start_mval_fl(const wmEvent *event, const ARegion *region, float r_mval[2])
|
|
|
|
|
{
|
2022-03-09 09:01:28 +11:00
|
|
|
const int *xy = (event->val == KM_CLICK_DRAG) ? event->prev_press_xy : event->xy;
|
2022-03-09 08:36:36 +11:00
|
|
|
r_mval[0] = xy[0] - region->winrct.xmin;
|
|
|
|
|
r_mval[1] = xy[1] - region->winrct.ymin;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WM_event_drag_start_xy(const wmEvent *event, int r_xy[2])
|
|
|
|
|
{
|
2022-03-09 09:01:28 +11:00
|
|
|
copy_v2_v2_int(r_xy, (event->val == KM_CLICK_DRAG) ? event->prev_press_xy : event->xy);
|
2022-03-09 08:36:36 +11:00
|
|
|
}
|
|
|
|
|
|
2020-01-10 17:27:53 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
2022-07-14 13:54:26 +10:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Event Text Queries
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
char WM_event_utf8_to_ascii(const wmEvent *event)
|
2022-07-14 13:54:26 +10:00
|
|
|
{
|
2023-09-18 13:36:17 +10:00
|
|
|
if (BLI_str_utf8_size_or_error(event->utf8_buf) == 1) {
|
2022-07-14 13:54:26 +10:00
|
|
|
return event->utf8_buf[0];
|
|
|
|
|
}
|
|
|
|
|
return '\0';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
2020-01-10 17:27:53 +11:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Event Preference Mapping
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
int WM_userdef_event_map(int kmitype)
|
|
|
|
|
{
|
|
|
|
|
switch (kmitype) {
|
|
|
|
|
case WHEELOUTMOUSE:
|
|
|
|
|
return (U.uiflag & USER_WHEELZOOMDIR) ? WHEELUPMOUSE : WHEELDOWNMOUSE;
|
|
|
|
|
case WHEELINMOUSE:
|
|
|
|
|
return (U.uiflag & USER_WHEELZOOMDIR) ? WHEELDOWNMOUSE : WHEELUPMOUSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return kmitype;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int WM_userdef_event_type_from_keymap_type(int kmitype)
|
|
|
|
|
{
|
|
|
|
|
switch (kmitype) {
|
|
|
|
|
case WHEELOUTMOUSE:
|
|
|
|
|
return (U.uiflag & USER_WHEELZOOMDIR) ? WHEELUPMOUSE : WHEELDOWNMOUSE;
|
|
|
|
|
case WHEELINMOUSE:
|
|
|
|
|
return (U.uiflag & USER_WHEELZOOMDIR) ? WHEELDOWNMOUSE : WHEELUPMOUSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return kmitype;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Event NDOF Input Access
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
#ifdef WITH_INPUT_NDOF
|
|
|
|
|
|
|
|
|
|
void WM_event_ndof_pan_get(const wmNDOFMotionData *ndof, float r_pan[3], const bool use_zoom)
|
|
|
|
|
{
|
|
|
|
|
int z_flag = use_zoom ? NDOF_ZOOM_INVERT : NDOF_PANZ_INVERT_AXIS;
|
|
|
|
|
r_pan[0] = ndof->tvec[0] * ((U.ndof_flag & NDOF_PANX_INVERT_AXIS) ? -1.0f : 1.0f);
|
|
|
|
|
r_pan[1] = ndof->tvec[1] * ((U.ndof_flag & NDOF_PANY_INVERT_AXIS) ? -1.0f : 1.0f);
|
|
|
|
|
r_pan[2] = ndof->tvec[2] * ((U.ndof_flag & z_flag) ? -1.0f : 1.0f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WM_event_ndof_rotate_get(const wmNDOFMotionData *ndof, float r_rot[3])
|
|
|
|
|
{
|
|
|
|
|
r_rot[0] = ndof->rvec[0] * ((U.ndof_flag & NDOF_ROTX_INVERT_AXIS) ? -1.0f : 1.0f);
|
|
|
|
|
r_rot[1] = ndof->rvec[1] * ((U.ndof_flag & NDOF_ROTY_INVERT_AXIS) ? -1.0f : 1.0f);
|
|
|
|
|
r_rot[2] = ndof->rvec[2] * ((U.ndof_flag & NDOF_ROTZ_INVERT_AXIS) ? -1.0f : 1.0f);
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
float WM_event_ndof_to_axis_angle(const wmNDOFMotionData *ndof, float axis[3])
|
2020-01-10 17:27:53 +11:00
|
|
|
{
|
|
|
|
|
float angle;
|
|
|
|
|
angle = normalize_v3_v3(axis, ndof->rvec);
|
|
|
|
|
|
|
|
|
|
axis[0] = axis[0] * ((U.ndof_flag & NDOF_ROTX_INVERT_AXIS) ? -1.0f : 1.0f);
|
|
|
|
|
axis[1] = axis[1] * ((U.ndof_flag & NDOF_ROTY_INVERT_AXIS) ? -1.0f : 1.0f);
|
|
|
|
|
axis[2] = axis[2] * ((U.ndof_flag & NDOF_ROTZ_INVERT_AXIS) ? -1.0f : 1.0f);
|
|
|
|
|
|
|
|
|
|
return ndof->dt * angle;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
void WM_event_ndof_to_quat(const wmNDOFMotionData *ndof, float q[4])
|
2020-01-10 17:27:53 +11:00
|
|
|
{
|
|
|
|
|
float axis[3];
|
|
|
|
|
float angle;
|
|
|
|
|
|
|
|
|
|
angle = WM_event_ndof_to_axis_angle(ndof, axis);
|
|
|
|
|
axis_angle_to_quat(q, axis, angle);
|
|
|
|
|
}
|
|
|
|
|
#endif /* WITH_INPUT_NDOF */
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
XR Controller Support Step 3: XR Events
Integrates XR input actions with the WM event system. With this commit,
all VR action functionality (operator execution, pose querying, haptic
application), with the exception of custom drawing, is enabled.
By itself, this does not bring about any changes for regular users,
however it is necessary for the upcoming VR add-on update that will
expose default controller actions to users.
For add-on developers, this updates the Python API with access to XR
event data (input states, controller poses, etc.), which can be
obtained via the "xr" property added to the bpy.types.Event struct.
For XR events, this property will be non-null and the event will have
the type XR_ACTION.
Further details:
XR-type window events are queued to the regular window queues after
updating and interpreting VR action states. An appropriate window is
found by either using the window the VR session was started in or a
fallback option.
When handling XR events, mouse-specific processing is skipped and
instead a dedicated XR offscreen area and region (see 08511b1c3de0) is
used to execute XR event operators in the proper context.
Reviewed By: Severin
Differential Revision: https://developer.blender.org/D10944
2021-10-12 13:09:01 +09:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Event XR Input Access
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
#ifdef WITH_XR_OPENXR
|
2023-06-03 08:36:28 +10:00
|
|
|
bool WM_event_is_xr(const wmEvent *event)
|
XR Controller Support Step 3: XR Events
Integrates XR input actions with the WM event system. With this commit,
all VR action functionality (operator execution, pose querying, haptic
application), with the exception of custom drawing, is enabled.
By itself, this does not bring about any changes for regular users,
however it is necessary for the upcoming VR add-on update that will
expose default controller actions to users.
For add-on developers, this updates the Python API with access to XR
event data (input states, controller poses, etc.), which can be
obtained via the "xr" property added to the bpy.types.Event struct.
For XR events, this property will be non-null and the event will have
the type XR_ACTION.
Further details:
XR-type window events are queued to the regular window queues after
updating and interpreting VR action states. An appropriate window is
found by either using the window the VR session was started in or a
fallback option.
When handling XR events, mouse-specific processing is skipped and
instead a dedicated XR offscreen area and region (see 08511b1c3de0) is
used to execute XR event operators in the proper context.
Reviewed By: Severin
Differential Revision: https://developer.blender.org/D10944
2021-10-12 13:09:01 +09:00
|
|
|
{
|
|
|
|
|
return (event->type == EVT_XR_ACTION && event->custom == EVT_DATA_XR);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
2020-01-10 17:27:53 +11:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Event Tablet Input Access
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
float wm_pressure_curve(float pressure)
|
|
|
|
|
{
|
|
|
|
|
if (U.pressure_threshold_max != 0.0f) {
|
|
|
|
|
pressure /= U.pressure_threshold_max;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CLAMP(pressure, 0.0f, 1.0f);
|
|
|
|
|
|
|
|
|
|
if (U.pressure_softness != 0.0f) {
|
|
|
|
|
pressure = powf(pressure, powf(4.0f, -U.pressure_softness));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return pressure;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float WM_event_tablet_data(const wmEvent *event, int *pen_flip, float tilt[2])
|
|
|
|
|
{
|
|
|
|
|
if (tilt) {
|
2020-01-10 16:54:17 +01:00
|
|
|
tilt[0] = event->tablet.x_tilt;
|
|
|
|
|
tilt[1] = event->tablet.y_tilt;
|
2020-01-10 17:27:53 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pen_flip) {
|
2020-01-10 16:54:17 +01:00
|
|
|
(*pen_flip) = (event->tablet.active == EVT_TABLET_ERASER);
|
2020-01-10 17:27:53 +11:00
|
|
|
}
|
|
|
|
|
|
2020-01-10 16:54:17 +01:00
|
|
|
return event->tablet.pressure;
|
2020-01-10 17:27:53 +11:00
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
bool WM_event_is_tablet(const wmEvent *event)
|
2020-01-10 17:27:53 +11:00
|
|
|
{
|
2020-01-10 16:54:17 +01:00
|
|
|
return (event->tablet.active != EVT_TABLET_NONE);
|
2020-01-10 17:27:53 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
2020-11-09 12:26:53 +01:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Event Scroll's Absolute Deltas
|
|
|
|
|
*
|
|
|
|
|
* User may change the scroll behavior, and the deltas are automatically inverted.
|
|
|
|
|
* These functions return the absolute direction, swipe up/right gives positive values.
|
|
|
|
|
*
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
int WM_event_absolute_delta_x(const wmEvent *event)
|
2020-11-09 12:26:53 +01:00
|
|
|
{
|
2021-10-20 23:45:30 +11:00
|
|
|
int dx = event->xy[0] - event->prev_xy[0];
|
2020-11-09 12:26:53 +01:00
|
|
|
|
2022-03-01 11:59:21 +11:00
|
|
|
if ((event->flag & WM_EVENT_SCROLL_INVERT) == 0) {
|
2020-11-09 12:26:53 +01:00
|
|
|
dx = -dx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return dx;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
int WM_event_absolute_delta_y(const wmEvent *event)
|
2020-11-09 12:26:53 +01:00
|
|
|
{
|
2021-10-20 23:45:30 +11:00
|
|
|
int dy = event->xy[1] - event->prev_xy[1];
|
2020-11-09 12:26:53 +01:00
|
|
|
|
2022-03-01 11:59:21 +11:00
|
|
|
if ((event->flag & WM_EVENT_SCROLL_INVERT) == 0) {
|
2020-11-09 12:26:53 +01:00
|
|
|
dy = -dy;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return dy;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
2020-01-10 17:27:53 +11:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Event IME Input Access
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
#ifdef WITH_INPUT_IME
|
2021-07-07 12:55:19 +10:00
|
|
|
/**
|
|
|
|
|
* Most OS's use `Ctrl+Space` / `OsKey+Space` to switch IME,
|
|
|
|
|
* so don't type in the space character.
|
2021-07-27 18:12:46 +10:00
|
|
|
*
|
2023-02-12 14:37:16 +11:00
|
|
|
* \note Shift is excluded from this check since it prevented typing `Shift+Space`, see: #85517.
|
2021-07-07 12:55:19 +10:00
|
|
|
*/
|
2020-01-10 17:27:53 +11:00
|
|
|
bool WM_event_is_ime_switch(const struct wmEvent *event)
|
|
|
|
|
{
|
2022-02-24 22:48:34 +11:00
|
|
|
return (event->val == KM_PRESS) && (event->type == EVT_SPACEKEY) &&
|
|
|
|
|
(event->modifier & (KM_CTRL | KM_OSKEY | KM_ALT));
|
2020-01-10 17:27:53 +11:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/** \} */
|