diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index 2f426b4653a..70d8c422d6c 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -142,6 +142,7 @@ typedef struct GHOST_TabletData { 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 Twist; /* range (-pi,pi), stylus button side towards left is 0.0. */ } GHOST_TabletData; static const GHOST_TabletData GHOST_TABLET_DATA_NONE = { diff --git a/intern/ghost/intern/GHOST_SystemX11.cc b/intern/ghost/intern/GHOST_SystemX11.cc index 9b2952d92a3..b1ab11a68d5 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cc +++ b/intern/ghost/intern/GHOST_SystemX11.cc @@ -59,6 +59,9 @@ #include #include +/* M_PI */ +#include + #include /* for fprintf only */ #include /* for exit */ #include @@ -1558,6 +1561,13 @@ void GHOST_SystemX11::processEvent(XEvent *xe) window->GetTabletData().Ytilt = short(axis_value & 0xffff) / float(xtablet.YtiltLevels); } + if (AXIS_VALUE_GET(5, axis_value)) { + window->GetTabletData().Twist = short(axis_value & 0xffff) / + float(xtablet.TwistLevels) * M_PI; +# ifdef WITH_GHOST_DEBUG + printf("Twist: %f\n", window->GetTabletData().Twist); +# endif + } # undef AXIS_VALUE_GET } @@ -2721,6 +2731,12 @@ void GHOST_SystemX11::refreshXInputDevices() xtablet.XtiltLevels = 0; xtablet.YtiltLevels = 0; } + if (xvi->num_axes > 5) { + xtablet.TwistLevels = xvi->axes[5].max_value; + } + else { + xtablet.TwistLevels = 0; + } break; } diff --git a/intern/ghost/intern/GHOST_SystemX11.hh b/intern/ghost/intern/GHOST_SystemX11.hh index 4e8dc4d610a..b8df6bf9fcc 100644 --- a/intern/ghost/intern/GHOST_SystemX11.hh +++ b/intern/ghost/intern/GHOST_SystemX11.hh @@ -271,6 +271,7 @@ class GHOST_SystemX11 : public GHOST_System { int PressureLevels; int XtiltLevels, YtiltLevels; + int TwistLevels; } GHOST_TabletX11; std::vector &GetXTablets() diff --git a/intern/ghost/intern/GHOST_WindowWin32.cc b/intern/ghost/intern/GHOST_WindowWin32.cc index c0c26557f8b..d466201802a 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cc +++ b/intern/ghost/intern/GHOST_WindowWin32.cc @@ -5,6 +5,8 @@ * \ingroup GHOST */ +#define _USE_MATH_DEFINES + #include "GHOST_WindowWin32.hh" #include "GHOST_ContextD3D.hh" #include "GHOST_ContextNone.hh" @@ -953,6 +955,7 @@ GHOST_TSuccess GHOST_WindowWin32::getPointerInfo( outPointerInfo[i].tabletData.Pressure = 1.0f; outPointerInfo[i].tabletData.Xtilt = 0.0f; outPointerInfo[i].tabletData.Ytilt = 0.0f; + outPointerInfo[i].tabletData.Twist = 0.0f; outPointerInfo[i].time = system->performanceCounterToMillis(pointerApiInfo.PerformanceCount); if (pointerPenInfo[i].penMask & PEN_MASK_PRESSURE) { @@ -970,6 +973,13 @@ GHOST_TSuccess GHOST_WindowWin32::getPointerInfo( if (pointerPenInfo[i].penMask & PEN_MASK_TILT_Y) { outPointerInfo[i].tabletData.Ytilt = fmin(fabs(pointerPenInfo[i].tiltY / 90.0f), 1.0f); } + + if (pointerPenInfo[i].penMask & PEN_MASK_ROTATION) { + /* POINTER_PEN_INFO specifies rotation range to be [0,359], convert to radiant here. */ + outPointerInfo[i].tabletData.Twist = ((float)pointerPenInfo[i].rotation / 360.0f) * M_PI * 2; + /* Debug only. */ + printf("Twist (ink): %f\n", outPointerInfo[i].tabletData.Twist); + } } if (!outPointerInfo.empty()) { diff --git a/intern/ghost/intern/GHOST_Wintab.cc b/intern/ghost/intern/GHOST_Wintab.cc index 1045debf279..1dc0411cb5b 100644 --- a/intern/ghost/intern/GHOST_Wintab.cc +++ b/intern/ghost/intern/GHOST_Wintab.cc @@ -263,7 +263,7 @@ void GHOST_Wintab::remapCoordinates() void GHOST_Wintab::updateCursorInfo() { - AXIS Pressure, Orientation[3]; + AXIS Pressure, Orientation[3], Rotation; BOOL pressureSupport = m_fpInfo(WTI_DEVICES, DVC_NPRESSURE, &Pressure); m_maxPressure = pressureSupport ? Pressure.axMax : 0; @@ -278,11 +278,23 @@ void GHOST_Wintab::updateCursorInfo() else { m_maxAzimuth = m_maxAltitude = 0; } - WINTAB_PRINTF("HCTX %p %s maxAzimuth: %d, maxAltitude: %d\n", + + if (Orientation[2].axResolution) { + m_maxTwist = Orientation[2].axMax; + } + else { + BOOL rotationSupport = m_fpInfo(WTI_DEVICES, DVC_ROTATION, &Rotation); + if (rotationSupport && Rotation.axResolution) { + m_maxTwist = Rotation.axMax; + } + } + + WINTAB_PRINTF("HCTX %p %s maxAzimuth: %d, maxAltitude: %d, maxTwist: %d\n", m_context.get(), __func__, m_maxAzimuth, - m_maxAltitude); + m_maxAltitude, + m_maxTwist); } void GHOST_Wintab::processInfoChange(LPARAM lParam) @@ -362,6 +374,11 @@ void GHOST_Wintab::getInput(std::vector &outWintabInfo) out.tabletData.Ytilt = float(sin(M_PI_2 - azmRad) * vecLen); } + if (m_maxTwist > 0) { + ORIENTATION ort = pkt.pkOrientation; + out.tabletData.Twist = float(float(ort.orTwist) / float(m_maxTwist) * M_PI); + } + out.time = pkt.pkTime; /* Some Wintab libraries don't handle relative button input, so we track button presses diff --git a/intern/ghost/intern/GHOST_Wintab.hh b/intern/ghost/intern/GHOST_Wintab.hh index 565aeb6ca02..de9c1bbfb31 100644 --- a/intern/ghost/intern/GHOST_Wintab.hh +++ b/intern/ghost/intern/GHOST_Wintab.hh @@ -214,6 +214,7 @@ class GHOST_Wintab { int m_maxPressure = 0; int m_maxAzimuth = 0; int m_maxAltitude = 0; + int m_maxTwist = 0; /** Number of connected Wintab devices. */ UINT m_numDevices = 0; diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index e87e510e12a..4928fa4e78a 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -639,6 +639,8 @@ typedef struct wmTabletData { float x_tilt; /** as above. */ float y_tilt; + /** range (-pi,pi), with stylus button to the left side being 0. */ + float twist; /** Interpret mouse motion as absolute as typical for tablets. */ char is_motion_absolute; } wmTabletData; diff --git a/source/blender/windowmanager/intern/wm_event_system.cc b/source/blender/windowmanager/intern/wm_event_system.cc index 90869667e2b..15a7f24edd6 100644 --- a/source/blender/windowmanager/intern/wm_event_system.cc +++ b/source/blender/windowmanager/intern/wm_event_system.cc @@ -5138,6 +5138,7 @@ void wm_tablet_data_from_ghost(const GHOST_TabletData *tablet_data, wmTabletData wmtab->pressure = wm_pressure_curve(tablet_data->Pressure); wmtab->x_tilt = tablet_data->Xtilt; wmtab->y_tilt = tablet_data->Ytilt; + wmtab->twist = tablet_data->Twist; /* We could have a preference to support relative tablet motion (we can't detect that). */ wmtab->is_motion_absolute = true; // printf("%s: using tablet %.5f\n", __func__, wmtab->pressure);