mirror of
https://github.com/godotengine/godot
synced 2024-11-02 14:43:31 +00:00
[macOS, Windows, X11] Add stylus inverted/eraser support to
InputEventMouseMotion event
This commit is contained in:
parent
d572d3d2ab
commit
6dcc9d1131
9 changed files with 70 additions and 10 deletions
|
@ -741,6 +741,14 @@ float InputEventMouseMotion::get_pressure() const {
|
|||
return pressure;
|
||||
}
|
||||
|
||||
void InputEventMouseMotion::set_pen_inverted(bool p_inverted) {
|
||||
pen_inverted = p_inverted;
|
||||
}
|
||||
|
||||
bool InputEventMouseMotion::get_pen_inverted() const {
|
||||
return pen_inverted;
|
||||
}
|
||||
|
||||
void InputEventMouseMotion::set_relative(const Vector2 &p_relative) {
|
||||
relative = p_relative;
|
||||
}
|
||||
|
@ -768,6 +776,7 @@ Ref<InputEvent> InputEventMouseMotion::xformed_by(const Transform2D &p_xform, co
|
|||
|
||||
mm->set_position(p_xform.xform(get_position() + p_local_ofs));
|
||||
mm->set_pressure(get_pressure());
|
||||
mm->set_pen_inverted(get_pen_inverted());
|
||||
mm->set_tilt(get_tilt());
|
||||
mm->set_global_position(get_global_position());
|
||||
|
||||
|
@ -805,9 +814,9 @@ String InputEventMouseMotion::to_string() {
|
|||
break;
|
||||
}
|
||||
|
||||
// Work around the fact vformat can only take 5 substitutions but 6 need to be passed.
|
||||
String mask_and_position = vformat("button_mask=%s, position=(%s)", button_mask_string, String(get_position()));
|
||||
return vformat("InputEventMouseMotion: %s, relative=(%s), velocity=(%s), pressure=%.2f, tilt=(%s)", mask_and_position, String(get_relative()), String(get_velocity()), get_pressure(), String(get_tilt()));
|
||||
// Work around the fact vformat can only take 5 substitutions but 7 need to be passed.
|
||||
String mask_and_position_and_relative = vformat("button_mask=%s, position=(%s), relative=(%s)", button_mask_string, String(get_position()), String(get_relative()));
|
||||
return vformat("InputEventMouseMotion: %s, velocity=(%s), pressure=%.2f, tilt=(%s), pen_inverted=(%d)", mask_and_position_and_relative, String(get_velocity()), get_pressure(), String(get_tilt()), get_pen_inverted());
|
||||
}
|
||||
|
||||
bool InputEventMouseMotion::accumulate(const Ref<InputEvent> &p_event) {
|
||||
|
@ -859,6 +868,9 @@ void InputEventMouseMotion::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_pressure", "pressure"), &InputEventMouseMotion::set_pressure);
|
||||
ClassDB::bind_method(D_METHOD("get_pressure"), &InputEventMouseMotion::get_pressure);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_pen_inverted", "pen_inverted"), &InputEventMouseMotion::set_pen_inverted);
|
||||
ClassDB::bind_method(D_METHOD("get_pen_inverted"), &InputEventMouseMotion::get_pen_inverted);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_relative", "relative"), &InputEventMouseMotion::set_relative);
|
||||
ClassDB::bind_method(D_METHOD("get_relative"), &InputEventMouseMotion::get_relative);
|
||||
|
||||
|
@ -867,6 +879,7 @@ void InputEventMouseMotion::_bind_methods() {
|
|||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "tilt"), "set_tilt", "get_tilt");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pressure"), "set_pressure", "get_pressure");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pen_inverted"), "set_pen_inverted", "get_pen_inverted");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "relative", PROPERTY_HINT_NONE, "suffix:px"), "set_relative", "get_relative");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "velocity", PROPERTY_HINT_NONE, "suffix:px/s"), "set_velocity", "get_velocity");
|
||||
}
|
||||
|
|
|
@ -272,6 +272,7 @@ class InputEventMouseMotion : public InputEventMouse {
|
|||
float pressure = 0;
|
||||
Vector2 relative;
|
||||
Vector2 velocity;
|
||||
bool pen_inverted = false;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
@ -283,6 +284,9 @@ public:
|
|||
void set_pressure(float p_pressure);
|
||||
float get_pressure() const;
|
||||
|
||||
void set_pen_inverted(bool p_inverted);
|
||||
bool get_pen_inverted() const;
|
||||
|
||||
void set_relative(const Vector2 &p_relative);
|
||||
Vector2 get_relative() const;
|
||||
|
||||
|
|
|
@ -12,6 +12,10 @@
|
|||
<link title="3D Voxel Demo">https://godotengine.org/asset-library/asset/676</link>
|
||||
</tutorials>
|
||||
<members>
|
||||
<member name="pen_inverted" type="bool" setter="set_pen_inverted" getter="get_pen_inverted" default="false">
|
||||
Returns [code]true[/code] when using the eraser end of a stylus pen.
|
||||
[b]Note:[/b] This property is implemented on Linux, macOS and Windows.
|
||||
</member>
|
||||
<member name="pressure" type="float" setter="set_pressure" getter="get_pressure" default="0.0">
|
||||
Represents the pressure the user puts on the pen. Ranges from [code]0.0[/code] to [code]1.0[/code].
|
||||
</member>
|
||||
|
|
|
@ -196,6 +196,7 @@ bool DisplayServerX11::_refresh_device_info() {
|
|||
|
||||
xi.absolute_devices.clear();
|
||||
xi.touch_devices.clear();
|
||||
xi.pen_inverted_devices.clear();
|
||||
|
||||
int dev_count;
|
||||
XIDeviceInfo *info = XIQueryDevice(x11_display, XIAllDevices, &dev_count);
|
||||
|
@ -205,7 +206,7 @@ bool DisplayServerX11::_refresh_device_info() {
|
|||
if (!dev->enabled) {
|
||||
continue;
|
||||
}
|
||||
if (!(dev->use == XIMasterPointer || dev->use == XIFloatingSlave)) {
|
||||
if (!(dev->use == XISlavePointer || dev->use == XIFloatingSlave)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -274,6 +275,7 @@ bool DisplayServerX11::_refresh_device_info() {
|
|||
xi.pen_pressure_range[dev->deviceid] = Vector2(pressure_min, pressure_max);
|
||||
xi.pen_tilt_x_range[dev->deviceid] = Vector2(tilt_x_min, tilt_x_max);
|
||||
xi.pen_tilt_y_range[dev->deviceid] = Vector2(tilt_y_min, tilt_y_max);
|
||||
xi.pen_inverted_devices[dev->deviceid] = (bool)strstr(dev->name, "eraser");
|
||||
}
|
||||
|
||||
XIFreeDeviceInfo(info);
|
||||
|
@ -3438,7 +3440,7 @@ void DisplayServerX11::process_events() {
|
|||
} break;
|
||||
case XI_RawMotion: {
|
||||
XIRawEvent *raw_event = (XIRawEvent *)event_data;
|
||||
int device_id = raw_event->deviceid;
|
||||
int device_id = raw_event->sourceid;
|
||||
|
||||
// Determine the axis used (called valuators in XInput for some forsaken reason)
|
||||
// Mask is a bitmask indicating which axes are involved.
|
||||
|
@ -3504,6 +3506,11 @@ void DisplayServerX11::process_events() {
|
|||
values++;
|
||||
}
|
||||
|
||||
HashMap<int, bool>::Iterator pen_inverted = xi.pen_inverted_devices.find(device_id);
|
||||
if (pen_inverted) {
|
||||
xi.pen_inverted = pen_inverted->value;
|
||||
}
|
||||
|
||||
// https://bugs.freedesktop.org/show_bug.cgi?id=71609
|
||||
// http://lists.libsdl.org/pipermail/commits-libsdl.org/2015-June/000282.html
|
||||
if (raw_event->time == xi.last_relative_time && rel_x == xi.relative_motion.x && rel_y == xi.relative_motion.y) {
|
||||
|
@ -3936,6 +3943,7 @@ void DisplayServerX11::process_events() {
|
|||
mm->set_pressure(bool(mouse_get_button_state() & MouseButton::MASK_LEFT) ? 1.0f : 0.0f);
|
||||
}
|
||||
mm->set_tilt(xi.tilt);
|
||||
mm->set_pen_inverted(xi.pen_inverted);
|
||||
|
||||
_get_key_modifier_state(event.xmotion.state, mm);
|
||||
mm->set_button_mask((MouseButton)mouse_get_button_state());
|
||||
|
|
|
@ -201,10 +201,12 @@ class DisplayServerX11 : public DisplayServer {
|
|||
HashMap<int, Vector2> pen_pressure_range;
|
||||
HashMap<int, Vector2> pen_tilt_x_range;
|
||||
HashMap<int, Vector2> pen_tilt_y_range;
|
||||
HashMap<int, bool> pen_inverted_devices;
|
||||
XIEventMask all_event_mask;
|
||||
HashMap<int, Vector2> state;
|
||||
double pressure;
|
||||
bool pressure_supported;
|
||||
bool pen_inverted;
|
||||
Vector2 tilt;
|
||||
Vector2 mouse_pos_to_filter;
|
||||
Vector2 relative_motion;
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
bool ime_input_event_in_progress;
|
||||
bool mouse_down_control;
|
||||
bool ignore_momentum_scroll;
|
||||
bool last_pen_inverted;
|
||||
}
|
||||
|
||||
- (void)processScrollEvent:(NSEvent *)event button:(MouseButton)button factor:(double)factor;
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
ime_input_event_in_progress = false;
|
||||
mouse_down_control = false;
|
||||
ignore_momentum_scroll = false;
|
||||
last_pen_inverted = false;
|
||||
[self updateTrackingAreas];
|
||||
|
||||
if (@available(macOS 10.13, *)) {
|
||||
|
@ -377,9 +378,15 @@
|
|||
ds->update_mouse_pos(wd, mpos);
|
||||
mm->set_position(wd.mouse_pos);
|
||||
mm->set_pressure([event pressure]);
|
||||
if ([event subtype] == NSEventSubtypeTabletPoint) {
|
||||
NSEventSubtype subtype = [event subtype];
|
||||
if (subtype == NSEventSubtypeTabletPoint) {
|
||||
const NSPoint p = [event tilt];
|
||||
mm->set_tilt(Vector2(p.x, p.y));
|
||||
mm->set_pen_inverted(last_pen_inverted);
|
||||
} else if (subtype == NSEventSubtypeTabletProximity) {
|
||||
// Check if using the eraser end of pen only on proximity event.
|
||||
last_pen_inverted = [event pointingDeviceType] == NSPointingDeviceTypeEraser;
|
||||
mm->set_pen_inverted(last_pen_inverted);
|
||||
}
|
||||
mm->set_global_position(wd.mouse_pos);
|
||||
mm->set_velocity(Input::get_singleton()->get_last_mouse_velocity());
|
||||
|
|
|
@ -2490,6 +2490,8 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
|
|||
windows[window_id].last_tilt = Vector2();
|
||||
}
|
||||
|
||||
windows[window_id].last_pen_inverted = packet.pkStatus & TPS_INVERT;
|
||||
|
||||
POINT coords;
|
||||
GetCursorPos(&coords);
|
||||
ScreenToClient(windows[window_id].hWnd, &coords);
|
||||
|
@ -2508,6 +2510,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
|
|||
|
||||
mm->set_pressure(windows[window_id].last_pressure);
|
||||
mm->set_tilt(windows[window_id].last_tilt);
|
||||
mm->set_pen_inverted(windows[window_id].last_pen_inverted);
|
||||
|
||||
mm->set_button_mask(last_button_state);
|
||||
|
||||
|
@ -2640,6 +2643,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
|
|||
if ((pen_info.penMask & PEN_MASK_TILT_X) && (pen_info.penMask & PEN_MASK_TILT_Y)) {
|
||||
mm->set_tilt(Vector2((float)pen_info.tiltX / 90, (float)pen_info.tiltY / 90));
|
||||
}
|
||||
mm->set_pen_inverted(pen_info.penFlags & (PEN_FLAG_INVERTED | PEN_FLAG_ERASER));
|
||||
|
||||
mm->set_ctrl_pressed(GetKeyState(VK_CONTROL) < 0);
|
||||
mm->set_shift_pressed(GetKeyState(VK_SHIFT) < 0);
|
||||
|
@ -2742,14 +2746,17 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
|
|||
} else {
|
||||
windows[window_id].last_tilt = Vector2();
|
||||
windows[window_id].last_pressure = (wParam & MK_LBUTTON) ? 1.0f : 0.0f;
|
||||
windows[window_id].last_pen_inverted = false;
|
||||
}
|
||||
} else {
|
||||
windows[window_id].last_tilt = Vector2();
|
||||
windows[window_id].last_pressure = (wParam & MK_LBUTTON) ? 1.0f : 0.0f;
|
||||
windows[window_id].last_pen_inverted = false;
|
||||
}
|
||||
|
||||
mm->set_pressure(windows[window_id].last_pressure);
|
||||
mm->set_tilt(windows[window_id].last_tilt);
|
||||
mm->set_pen_inverted(windows[window_id].last_pen_inverted);
|
||||
|
||||
mm->set_button_mask(last_button_state);
|
||||
|
||||
|
@ -3360,8 +3367,8 @@ void DisplayServerWindows::_update_tablet_ctx(const String &p_old_driver, const
|
|||
if ((p_new_driver == "wintab") && wintab_available) {
|
||||
wintab_WTInfo(WTI_DEFSYSCTX, 0, &wd.wtlc);
|
||||
wd.wtlc.lcOptions |= CXO_MESSAGES;
|
||||
wd.wtlc.lcPktData = PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION;
|
||||
wd.wtlc.lcMoveMask = PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE;
|
||||
wd.wtlc.lcPktData = PK_STATUS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION;
|
||||
wd.wtlc.lcMoveMask = PK_STATUS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE;
|
||||
wd.wtlc.lcPktMode = 0;
|
||||
wd.wtlc.lcOutOrgX = 0;
|
||||
wd.wtlc.lcOutExtX = wd.wtlc.lcInExtX;
|
||||
|
@ -3484,8 +3491,8 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
|
|||
if ((tablet_get_current_driver() == "wintab") && wintab_available) {
|
||||
wintab_WTInfo(WTI_DEFSYSCTX, 0, &wd.wtlc);
|
||||
wd.wtlc.lcOptions |= CXO_MESSAGES;
|
||||
wd.wtlc.lcPktData = PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION;
|
||||
wd.wtlc.lcMoveMask = PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE;
|
||||
wd.wtlc.lcPktData = PK_STATUS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION;
|
||||
wd.wtlc.lcMoveMask = PK_STATUS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE;
|
||||
wd.wtlc.lcPktMode = 0;
|
||||
wd.wtlc.lcOutOrgX = 0;
|
||||
wd.wtlc.lcOutExtX = wd.wtlc.lcInExtX;
|
||||
|
|
|
@ -82,10 +82,13 @@
|
|||
#define DVC_ROTATION 18
|
||||
|
||||
#define CXO_MESSAGES 0x0004
|
||||
#define PK_STATUS 0x0002
|
||||
#define PK_NORMAL_PRESSURE 0x0400
|
||||
#define PK_TANGENT_PRESSURE 0x0800
|
||||
#define PK_ORIENTATION 0x1000
|
||||
|
||||
#define TPS_INVERT 0x0010 /* 1.1 */
|
||||
|
||||
typedef struct tagLOGCONTEXTW {
|
||||
WCHAR lcName[40];
|
||||
UINT lcOptions;
|
||||
|
@ -137,6 +140,7 @@ typedef struct tagORIENTATION {
|
|||
} ORIENTATION;
|
||||
|
||||
typedef struct tagPACKET {
|
||||
int pkStatus;
|
||||
int pkNormalPressure;
|
||||
int pkTangentPressure;
|
||||
ORIENTATION pkOrientation;
|
||||
|
@ -158,6 +162,14 @@ typedef UINT32 POINTER_FLAGS;
|
|||
typedef UINT32 PEN_FLAGS;
|
||||
typedef UINT32 PEN_MASK;
|
||||
|
||||
#ifndef PEN_FLAG_INVERTED
|
||||
#define PEN_FLAG_INVERTED 0x00000002
|
||||
#endif
|
||||
|
||||
#ifndef PEN_FLAG_ERASER
|
||||
#define PEN_FLAG_ERASER 0x00000004
|
||||
#endif
|
||||
|
||||
#ifndef PEN_MASK_PRESSURE
|
||||
#define PEN_MASK_PRESSURE 0x00000001
|
||||
#endif
|
||||
|
@ -357,11 +369,13 @@ class DisplayServerWindows : public DisplayServer {
|
|||
int min_pressure;
|
||||
int max_pressure;
|
||||
bool tilt_supported;
|
||||
bool pen_inverted = false;
|
||||
bool block_mm = false;
|
||||
|
||||
int last_pressure_update;
|
||||
float last_pressure;
|
||||
Vector2 last_tilt;
|
||||
bool last_pen_inverted = false;
|
||||
|
||||
HBITMAP hBitmap; //DIB section for layered window
|
||||
uint8_t *dib_data = nullptr;
|
||||
|
|
Loading…
Reference in a new issue