From e1e250aa84c1d9c60148b844ff7ccf4b8d22bd4a Mon Sep 17 00:00:00 2001 From: Harley Acheson Date: Tue, 15 Apr 2025 20:23:32 +0200 Subject: [PATCH] UI: Consistent Pen Tilt Values Pen tilt values come into Blender through ghost platforms and device drivers with inconsistent and ambiguous directions. This PR codifies that we consider tilt-x positive values to be rightward, negative values as leftward. Similarly tilt-y positive is away from the user, negative is toward the user. Comments are updated to make this clear. This fixes Windows Ink (currently always returning left and away). This also reverses the Wayland tily-y values to match. We might still have to consider a user preference to swap directions if we find differences within a platform. Pull Request: https://projects.blender.org/blender/blender/pulls/137501 --- intern/ghost/GHOST_Types.h | 4 ++-- intern/ghost/intern/GHOST_SystemCocoa.mm | 5 +++-- intern/ghost/intern/GHOST_SystemWayland.cc | 6 +++--- intern/ghost/intern/GHOST_WindowWin32.cc | 16 +++++++++++++--- source/blender/makesrna/intern/rna_brush.cc | 4 ++-- source/blender/windowmanager/WM_types.hh | 4 ++-- 6 files changed, 25 insertions(+), 14 deletions(-) diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index d04081f6d26..5f408f7dd08 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -165,8 +165,8 @@ typedef enum { typedef struct GHOST_TabletData { GHOST_TTabletMode Active; /* 0=None, 1=Stylus, 2=Eraser */ float Pressure; /* range 0.0 (not touching) to 1.0 (full pressure) */ - float Xtilt; /* range 0.0 (upright) to 1.0 (tilted fully against the tablet surface) */ - float Ytilt; /* as above */ + float Xtilt; /* range -1.0 (left) to +1.0 (right) */ + float Ytilt; /* range -1.0 (toward user) to +1.0 (away from user) */ } GHOST_TabletData; static const GHOST_TabletData GHOST_TABLET_DATA_NONE = { diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 5ff6af1ab05..c9f56cc4a8f 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -1481,9 +1481,10 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr, short eventT } ct.Pressure = event.pressure; + /* Range: -1 (left) to 1 (right). */ ct.Xtilt = event.tilt.x; - /* On macOS, the y tilt behavior is inverted; an increase in the tilt - * value corresponds to tilting the device away from the user. */ + /* On macOS, the y tilt behavior is inverted from what we expect: negative + * meaning a tilt toward the user, positive meaning away from the user. */ ct.Ytilt = -event.tilt.y; break; diff --git a/intern/ghost/intern/GHOST_SystemWayland.cc b/intern/ghost/intern/GHOST_SystemWayland.cc index 945da9f1c0e..43f53c46fc6 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cc +++ b/intern/ghost/intern/GHOST_SystemWayland.cc @@ -4791,10 +4791,10 @@ static void tablet_tool_handle_tilt(void *data, const wl_fixed_t tilt_x, const wl_fixed_t tilt_y) { - /* Map degrees to `-1.0..1.0`. */ + /* Map degrees to `-1.0 (left/back)..1.0 (right/forward)`. */ const float tilt_unit[2] = { - float(wl_fixed_to_double(tilt_x) / 90.0), - float(wl_fixed_to_double(tilt_y) / 90.0), + float(wl_fixed_to_double(tilt_x) / 90.0f), + float(wl_fixed_to_double(tilt_y) / -90.0f), }; CLOG_INFO(LOG, 2, "tilt (x=%.4f, y=%.4f)", UNPACK2(tilt_unit)); GWL_TabletTool *tablet_tool = static_cast(data); diff --git a/intern/ghost/intern/GHOST_WindowWin32.cc b/intern/ghost/intern/GHOST_WindowWin32.cc index 13f9b6ad5eb..54926323aba 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cc +++ b/intern/ghost/intern/GHOST_WindowWin32.cc @@ -6,12 +6,14 @@ * \ingroup GHOST */ -#include "GHOST_WindowWin32.hh" +#include + #include "GHOST_ContextD3D.hh" #include "GHOST_ContextNone.hh" #include "GHOST_DropTargetWin32.hh" #include "GHOST_SystemWin32.hh" #include "GHOST_WindowManager.hh" +#include "GHOST_WindowWin32.hh" #include "utf_winfunc.hh" #include "utfconv.hh" @@ -1022,11 +1024,19 @@ GHOST_TSuccess GHOST_WindowWin32::getPointerInfo( } if (pointerPenInfo[i].penMask & PEN_MASK_TILT_X) { - outPointerInfo[i].tabletData.Xtilt = fmin(fabs(pointerPenInfo[i].tiltX / 90.0f), 1.0f); + /* Input value is a range of -90 to +90, with a positive value + * indicating a tilt to the right. Convert to what Blender + * expects: -1.0f (left) to +1.0f (right). */ + outPointerInfo[i].tabletData.Xtilt = std::clamp( + pointerPenInfo[i].tiltX / 90.0f, -1.0f, 1.0f); } if (pointerPenInfo[i].penMask & PEN_MASK_TILT_Y) { - outPointerInfo[i].tabletData.Ytilt = fmin(fabs(pointerPenInfo[i].tiltY / 90.0f), 1.0f); + /* Input value is a range of -90 to +90, with a positive value + * indicating a tilt toward the user. Convert to what Blender + * expects: -1.0f (toward user) to +1.0f (away from user). */ + outPointerInfo[i].tabletData.Ytilt = std::clamp( + pointerPenInfo[i].tiltY / -90.0f, -1.0f, 1.0f); } } diff --git a/source/blender/makesrna/intern/rna_brush.cc b/source/blender/makesrna/intern/rna_brush.cc index f34da6e645c..83e6aeab645 100644 --- a/source/blender/makesrna/intern/rna_brush.cc +++ b/source/blender/makesrna/intern/rna_brush.cc @@ -3937,12 +3937,12 @@ static void rna_def_operator_stroke_element(BlenderRNA *brna) prop = RNA_def_property(srna, "x_tilt", PROP_FLOAT, PROP_FACTOR); RNA_def_property_flag(prop, PROP_IDPROPERTY); RNA_def_property_range(prop, -1.0f, 1.0f); - RNA_def_property_ui_text(prop, "Tilt X", ""); + RNA_def_property_ui_text(prop, "Tilt X", "Pen tilt from left (-1.0) to right (+1.0)"); prop = RNA_def_property(srna, "y_tilt", PROP_FLOAT, PROP_FACTOR); RNA_def_property_flag(prop, PROP_IDPROPERTY); RNA_def_property_range(prop, -1.0f, 1.0f); - RNA_def_property_ui_text(prop, "Tilt Y", ""); + RNA_def_property_ui_text(prop, "Tilt Y", "Pen tilt from forward (-1.0) to back (+1.0)"); /* used in uv painting */ prop = RNA_def_property(srna, "time", PROP_FLOAT, PROP_UNSIGNED); diff --git a/source/blender/windowmanager/WM_types.hh b/source/blender/windowmanager/WM_types.hh index 36bafdec0fe..d62fbd8f783 100644 --- a/source/blender/windowmanager/WM_types.hh +++ b/source/blender/windowmanager/WM_types.hh @@ -700,9 +700,9 @@ struct wmTabletData { int active; /** Range 0.0 (not touching) to 1.0 (full pressure). */ float pressure; - /** Range 0.0 (upright) to 1.0 (tilted fully against the tablet surface). */ + /** range -1.0 (left) to +1.0 (right). */ float x_tilt; - /** As above. */ + /** range -1.0 (toward user) to +1.0 (away from user). */ float y_tilt; /** Interpret mouse motion as absolute as typical for tablets. */ char is_motion_absolute;