WIP: Wacom twist support for GHOST #107729

Draft
YimingWu wants to merge 6 commits from ChengduLittleA/blender:ghost_twist into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
8 changed files with 52 additions and 3 deletions

View File

@ -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 = {

View File

@ -59,6 +59,9 @@
#include <sys/time.h>
#include <unistd.h>
/* M_PI */
#include <math.h>
#include <cstdio> /* for fprintf only */
#include <cstdlib> /* for exit */
#include <iostream>
@ -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;
}

View File

@ -271,6 +271,7 @@ class GHOST_SystemX11 : public GHOST_System {
int PressureLevels;
int XtiltLevels, YtiltLevels;
int TwistLevels;
} GHOST_TabletX11;
std::vector<GHOST_TabletX11> &GetXTablets()

View File

@ -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()) {

View File

@ -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<GHOST_WintabInfoWin32> &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

View File

@ -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;

View File

@ -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;

View File

@ -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);