forked from blender/blender
main sync #3
@ -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.
|
||||
|
@ -274,6 +274,13 @@ 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) {
|
||||
wmWindow *win = CTX_wm_window(C);
|
||||
const bool use_depth_last = ED_view3d_autodist_last_check(win, event);
|
||||
|
||||
if (use_depth_last) {
|
||||
vod->use_dyn_ofs = ED_view3d_autodist_last_get(win, vod->dyn_ofs);
|
||||
}
|
||||
else {
|
||||
float fallback_depth_pt[3];
|
||||
|
||||
view3d_operator_needs_opengl(C); /* Needed for Z-buffer drawing. */
|
||||
@ -282,8 +289,14 @@ ViewOpsData *viewops_data_create(bContext *C, const wmEvent *event, enum eViewOp
|
||||
|
||||
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;
|
||||
|
@ -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
|
||||
* \{ */
|
||||
|
@ -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.
|
||||
|
@ -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]");
|
||||
|
@ -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]);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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
|
||||
* \{ */
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user