main sync #3

Merged
Patrick Busch merged 318 commits from blender/blender:main into main 2023-03-17 15:52:21 +01:00
12 changed files with 283 additions and 16 deletions
Showing only changes of commit 01a29ebaeb - Show all commits

View File

@ -48,6 +48,7 @@ struct bPoseChannel;
struct bScreen;
struct rctf;
struct rcti;
struct wmEvent;
struct wmGizmo;
struct wmWindow;
struct wmWindowManager;
@ -863,6 +864,20 @@ int ED_view3d_backbuf_sample_size_clamp(struct ARegion *region, float dist);
void ED_view3d_select_id_validate(struct ViewContext *vc);
/** Check if the last auto-dist can be used. */
bool ED_view3d_autodist_last_check(struct wmWindow *win, const struct wmEvent *event);
/**
* \return true when `r_ofs` is set.
* \warning #ED_view3d_autodist_last_check should be called first to ensure the data is available.
*/
bool ED_view3d_autodist_last_get(struct wmWindow *win, float r_ofs[3]);
void ED_view3d_autodist_last_set(struct wmWindow *win,
const struct wmEvent *event,
const float ofs[3],
const bool has_depth);
/** Clear and free auto-dist data. */
void ED_view3d_autodist_last_clear(struct wmWindow *win);
/**
* Get the world-space 3d location from a screen-space 2d point.
* TODO: Implement #alphaoverride. We don't want to zoom into billboards.

View File

@ -274,16 +274,29 @@ ViewOpsData *viewops_data_create(bContext *C, const wmEvent *event, enum eViewOp
/* we need the depth info before changing any viewport options */
if (viewops_flag & VIEWOPS_FLAG_DEPTH_NAVIGATE) {
float fallback_depth_pt[3];
wmWindow *win = CTX_wm_window(C);
const bool use_depth_last = ED_view3d_autodist_last_check(win, event);
view3d_operator_needs_opengl(C); /* Needed for Z-buffer drawing. */
if (use_depth_last) {
vod->use_dyn_ofs = ED_view3d_autodist_last_get(win, vod->dyn_ofs);
}
else {
float fallback_depth_pt[3];
negate_v3_v3(fallback_depth_pt, rv3d->ofs);
view3d_operator_needs_opengl(C); /* Needed for Z-buffer drawing. */
vod->use_dyn_ofs = ED_view3d_autodist(
depsgraph, vod->region, vod->v3d, event->mval, vod->dyn_ofs, true, fallback_depth_pt);
negate_v3_v3(fallback_depth_pt, rv3d->ofs);
vod->use_dyn_ofs = ED_view3d_autodist(
depsgraph, vod->region, vod->v3d, event->mval, vod->dyn_ofs, true, fallback_depth_pt);
ED_view3d_autodist_last_set(win, event, vod->dyn_ofs, vod->use_dyn_ofs);
}
}
else {
wmWindow *win = CTX_wm_window(C);
ED_view3d_autodist_last_clear(win);
vod->use_dyn_ofs = false;
}
vod->init.persp = rv3d->persp;

View File

@ -1005,6 +1005,77 @@ void ED_view3d_quadview_update(ScrArea *area, ARegion *region, bool do_clip)
/** \} */
/* -------------------------------------------------------------------- */
/** \name View Auto-Depth Last State Access
*
* Calling consecutive track-pad gestures reuses the previous offset to prevent
* each track-pad event using a different offset, see: #103263.
* \{ */
static const char *view3d_autodepth_last_id = "view3d_autodist_last";
/**
* Auto-depth values for #ED_view3d_autodist_last_check and related functions.
*/
typedef struct View3D_AutoDistLast {
float ofs[3];
bool has_depth;
} View3D_AutoDistLast;
bool ED_view3d_autodist_last_check(wmWindow *win, const wmEvent *event)
{
if (event->flag & WM_EVENT_IS_CONSECUTIVE) {
const View3D_AutoDistLast *autodepth_last = WM_event_consecutive_data_get(
win, view3d_autodepth_last_id);
if (autodepth_last) {
return true;
}
}
return false;
}
void ED_view3d_autodist_last_clear(wmWindow *win)
{
WM_event_consecutive_data_free(win);
}
void ED_view3d_autodist_last_set(wmWindow *win,
const wmEvent *event,
const float ofs[3],
const bool has_depth)
{
ED_view3d_autodist_last_clear(win);
if (WM_event_consecutive_gesture_test(event)) {
View3D_AutoDistLast *autodepth_last = MEM_callocN(sizeof(*autodepth_last), __func__);
autodepth_last->has_depth = has_depth;
copy_v3_v3(autodepth_last->ofs, ofs);
WM_event_consecutive_data_set(win, view3d_autodepth_last_id, autodepth_last);
}
}
bool ED_view3d_autodist_last_get(wmWindow *win, float r_ofs[3])
{
const View3D_AutoDistLast *autodepth_last = WM_event_consecutive_data_get(
win, view3d_autodepth_last_id);
/* #ED_view3d_autodist_last_check should be called first. */
BLI_assert(autodepth_last);
if (autodepth_last == NULL) {
return false;
}
if (autodepth_last->has_depth == false) {
zero_v3(r_ofs);
return false;
}
copy_v3_v3(r_ofs, autodepth_last->ofs);
return true;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name View Auto-Depth Utilities
* \{ */

View File

@ -22,6 +22,7 @@ extern "C" {
struct wmWindow;
struct wmWindowManager;
struct wmEvent_ConsecutiveData;
struct wmEvent;
struct wmKeyConfig;
struct wmKeyMap;
@ -280,6 +281,15 @@ typedef struct wmWindow {
short grabcursor;
/** Internal: tag this for extra mouse-move event,
* makes cursors/buttons active on UI switching. */
/** Internal, lock pie creation from this event until released. */
short pie_event_type_lock;
/**
* Exception to the above rule for nested pies, store last pie event for operators
* that spawn a new pie right after destruction of last pie.
*/
short pie_event_type_last;
char addmousemove;
char tag_cursor_refresh;
@ -296,15 +306,12 @@ typedef struct wmWindow {
*/
char event_queue_check_drag_handled;
char _pad0[1];
/** Internal, lock pie creation from this event until released. */
short pie_event_type_lock;
/**
* Exception to the above rule for nested pies, store last pie event for operators
* that spawn a new pie right after destruction of last pie.
*/
short pie_event_type_last;
/** The last event type (that passed #WM_event_consecutive_gesture_test check). */
char event_queue_consecutive_gesture_type;
/** The cursor location when `event_queue_consecutive_gesture_type` was set. */
int event_queue_consecutive_gesture_xy[2];
/** See #WM_event_consecutive_data_get and related API. Freed when consecutive events end. */
struct wmEvent_ConsecutiveData *event_queue_consecutive_gesture_data;
/**
* Storage for event system.

View File

@ -664,6 +664,12 @@ static bool rna_Event_is_repeat_get(PointerRNA *ptr)
return (event->flag & WM_EVENT_IS_REPEAT) != 0;
}
static bool rna_Event_is_consecutive_get(PointerRNA *ptr)
{
const wmEvent *event = ptr->data;
return (event->flag & WM_EVENT_IS_CONSECUTIVE) != 0;
}
static float rna_Event_pressure_get(PointerRNA *ptr)
{
const wmEvent *event = ptr->data;
@ -2154,6 +2160,15 @@ static void rna_def_event(BlenderRNA *brna)
RNA_def_property_boolean_funcs(prop, "rna_Event_is_repeat_get", NULL);
RNA_def_property_ui_text(prop, "Is Repeat", "The event is generated by holding a key down");
/* Track-pad & NDOF. */
prop = RNA_def_property(srna, "is_consecutive", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_boolean_funcs(prop, "rna_Event_is_consecutive_get", NULL);
RNA_def_property_ui_text(prop,
"Is Consecutive",
"Part of a track-pad or NDOF motion, "
"interrupted by cursor motion, button or key press events");
/* mouse */
prop = RNA_def_property(srna, "mouse_x", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "xy[0]");

View File

@ -1258,6 +1258,15 @@ bool WM_gesture_is_modal_first(const struct wmGesture *gesture);
void WM_event_add_fileselect(struct bContext *C, struct wmOperator *op);
void WM_event_fileselect_event(struct wmWindowManager *wm, void *ophandle, int eventval);
/* Event consecutive data. */
/** Return a borrowed reference to the custom-data. */
void *WM_event_consecutive_data_get(wmWindow *win, const char *id);
/** Set the custom-data (and own the pointer), free with #MEM_freeN. */
void WM_event_consecutive_data_set(wmWindow *win, const char *id, void *custom_data);
/** Clear and free the consecutive custom-data. */
void WM_event_consecutive_data_free(wmWindow *win);
/**
* Sets the active region for this space from the context.
*
@ -1650,6 +1659,9 @@ char WM_event_utf8_to_ascii(const struct wmEvent *event) ATTR_NONNULL(1) ATTR_WA
*/
bool WM_cursor_test_motion_and_update(const int mval[2]) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
bool WM_event_consecutive_gesture_test(const wmEvent *event);
bool WM_event_consecutive_gesture_test_break(const wmWindow *win, const wmEvent *event);
int WM_event_drag_threshold(const struct wmEvent *event);
bool WM_event_drag_test(const struct wmEvent *event, const int prev_xy[2]);
bool WM_event_drag_test_with_delta(const struct wmEvent *event, const int delta[2]);

View File

@ -614,11 +614,19 @@ typedef enum eWM_EventFlag {
* See #KMI_REPEAT_IGNORE for details on how key-map handling uses this.
*/
WM_EVENT_IS_REPEAT = (1 << 1),
/**
* Generated for consecutive track-pad or NDOF-motion events,
* the repeat chain is broken by key/button events,
* or cursor motion exceeding #WM_EVENT_CURSOR_MOTION_THRESHOLD.
*
* Changing the type of track-pad or gesture event also breaks the chain.
*/
WM_EVENT_IS_CONSECUTIVE = (1 << 2),
/**
* Mouse-move events may have this flag set to force creating a click-drag event
* even when the threshold has not been met.
*/
WM_EVENT_FORCE_DRAG_THRESHOLD = (1 << 2),
WM_EVENT_FORCE_DRAG_THRESHOLD = (1 << 3),
} eWM_EventFlag;
ENUM_OPERATORS(eWM_EventFlag, WM_EVENT_FORCE_DRAG_THRESHOLD);

View File

@ -179,6 +179,8 @@ static void window_manager_blend_read_data(BlendDataReader *reader, ID *id)
win->event_queue_check_click = 0;
win->event_queue_check_drag = 0;
win->event_queue_check_drag_handled = 0;
win->event_queue_consecutive_gesture_type = 0;
win->event_queue_consecutive_gesture_data = NULL;
BLO_read_data_address(reader, &win->stereo3d_format);
/* Multi-view always fallback to anaglyph at file opening

View File

@ -103,6 +103,7 @@ void WM_event_print(const wmEvent *event)
struct FlagIdentifierPair flag_data[] = {
{"SCROLL_INVERT", WM_EVENT_SCROLL_INVERT},
{"IS_REPEAT", WM_EVENT_IS_REPEAT},
{"IS_CONSECUTIVE", WM_EVENT_IS_CONSECUTIVE},
{"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);
@ -336,6 +337,51 @@ bool WM_cursor_test_motion_and_update(const int mval[2])
/** \} */
/* -------------------------------------------------------------------- */
/** \name Event Consecutive Checks
* \{ */
/**
* Return true if this event type is a candidate for being flagged as consecutive.
*
* See: #WM_EVENT_IS_CONSECUTIVE doc-string.
*/
bool WM_event_consecutive_gesture_test(const wmEvent *event)
{
return ISMOUSE_GESTURE(event->type) || (event->type == NDOF_MOTION);
}
/**
* Return true if this event should break the chain of consecutive gestures.
* Practically all intentional user input should, key presses or button clicks.
*/
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;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Event Click/Drag Checks
*

View File

@ -3966,6 +3966,27 @@ void wm_event_do_handlers(bContext *C)
}
const bool event_queue_check_drag_prev = win->event_queue_check_drag;
{
const bool is_consecutive = WM_event_consecutive_gesture_test(event);
if (win->event_queue_consecutive_gesture_type != 0) {
if (event->type == win->event_queue_consecutive_gesture_type) {
event->flag |= WM_EVENT_IS_CONSECUTIVE;
}
else if (is_consecutive || WM_event_consecutive_gesture_test_break(win, event)) {
CLOG_INFO(WM_LOG_HANDLERS, 1, "consecutive gesture break (%d)", event->type);
win->event_queue_consecutive_gesture_type = 0;
WM_event_consecutive_data_free(win);
}
}
else if (is_consecutive) {
CLOG_INFO(WM_LOG_HANDLERS, 1, "consecutive gesture begin (%d)", event->type);
win->event_queue_consecutive_gesture_type = event->type;
copy_v2_v2_int(win->event_queue_consecutive_gesture_xy, event->xy);
/* While this should not be set, it's harmless to free here. */
WM_event_consecutive_data_free(win);
}
}
/* Active screen might change during handlers, update pointer. */
screen = WM_window_get_active_screen(win);
@ -4309,6 +4330,56 @@ void WM_event_add_fileselect(bContext *C, wmOperator *op)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Consecutive Event Access
* \{ */
using wmEvent_ConsecutiveData = struct wmEvent_ConsecutiveData {
/** Owned custom-data. */
void *custom_data;
/** Unique identifier per struct type. */
char id[0];
};
void *WM_event_consecutive_data_get(wmWindow *win, const char *id)
{
wmEvent_ConsecutiveData *cdata = win->event_queue_consecutive_gesture_data;
if (cdata && STREQ(cdata->id, id)) {
return cdata->custom_data;
}
return nullptr;
}
void WM_event_consecutive_data_set(wmWindow *win, const char *id, void *custom_data)
{
if (win->event_queue_consecutive_gesture_data) {
WM_event_consecutive_data_free(win);
}
const size_t id_size = strlen(id) + 1;
wmEvent_ConsecutiveData *cdata = static_cast<wmEvent_ConsecutiveData *>(
MEM_mallocN(sizeof(*cdata) + id_size, __func__));
cdata->custom_data = custom_data;
memcpy((cdata + 1), id, id_size);
win->event_queue_consecutive_gesture_data = cdata;
}
void WM_event_consecutive_data_free(wmWindow *win)
{
wmEvent_ConsecutiveData *cdata = win->event_queue_consecutive_gesture_data;
if (cdata == nullptr) {
return;
}
if (cdata->custom_data) {
MEM_freeN(cdata->custom_data);
}
MEM_freeN(cdata);
win->event_queue_consecutive_gesture_data = nullptr;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Modal Operator Handling
* \{ */

View File

@ -256,6 +256,9 @@ void wm_window_free(bContext *C, wmWindowManager *wm, wmWindow *win)
if (win->event_last_handled) {
MEM_freeN(win->event_last_handled);
}
if (win->event_queue_consecutive_gesture_data) {
WM_event_consecutive_data_free(win);
}
if (win->cursor_keymap_status) {
MEM_freeN(win->cursor_keymap_status);

View File

@ -60,7 +60,7 @@ enum {
/* More mouse buttons - can't use 9 and 10 here (wheel) */
BUTTON6MOUSE = 0x0012,
BUTTON7MOUSE = 0x0013,
/* Extra track-pad gestures. */
/* Extra track-pad gestures (check #WM_EVENT_IS_CONSECUTIVE to detect motion events). */
MOUSEPAN = 0x000e,
MOUSEZOOM = 0x000f,
MOUSEROTATE = 0x0010,
@ -247,6 +247,10 @@ enum {
* These must be kept in sync with `GHOST_NDOFManager.h`.
* Ordering matters, exact values do not. */
/**
* Motion from 3D input (translation & rotation).
* Check #WM_EVENT_IS_CONSECUTIVE to detect motion events.
*/
NDOF_MOTION = 0x0190, /* 400 */
#define _NDOF_MIN NDOF_MOTION