Skip to content

Add inversion/eraser-end detection for tablet pens #4702

Open
@hansemro

Description

Describe the project you are working on

Lorien (https://github.com/mbrlabs/Lorien), which is an infinite-canvas drawing program that benefits from pen/wacom/stylus input method. This project uses Godot 3.4/3.x

Describe the problem or limitation you are having in your project

I am currently working to resolve a feature request to map the eraser tool to the eraser-end of the pen (mbrlabs/Lorien#118). Implementing this feature requires checking whether the pen is inverted or not. However, Godot engine treats both ends the same and does not currently provide enough information to determine which end of the pen is used.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

Add pen_inverted boolean property and getter/setter functions (under InputEventMouseMotion) similar to how pen pressure is polled.

  • pen_inverted is true when eraser-end is used and false otherwise.
  • void set_pen_inverted(bool p_inverted) : requires platform-specific code to get status and then set event property.
  • bool get_pen_inverted(void) : used to poll inversion status

With this in place, my problem can be solved by polling inversion status and if-else statements to map a different tool on both ends of the pen.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

My proposal is based off my initial prototyping work: hansemro/godot#1

Development branches:

On a mouse-motion event, we leverage existing platform-specific APIs to determine and set the pen's inversion status. Once set, the event can be polled for pen_inverted property with get_pen_inverted. We do not expect game/project developers to use set_pen_inverted.

Most of the non-trivial work comes in handling platform-specific APIs. Below, I will cover some ideas that I have successfully tested in Godot 3.x tree. For unhandled platforms, we can assume the pen to not be inverted.

Windows

Both wintab and winink APIs have accessible properties to poll inversion status. Note that only wintab is expected to work under wine.

wintab API

Check for TPS_INVERT flag in WTPacket.pkStatus.

Relevant prototype commit: hansemro/godot@2af8a58

winink API

Check for PEN_FLAG_INVERTED or PEN_FLAG_ERASER flags in POINTER_PEN_INFO.penFlags.

Relevant prototype commit: hansemro/godot@75ca2cc

Linux/X11

When input devices are polled, check if the word "eraser" is in the device's name. If it is present, mark the device in a device map as inverted. The strstr implementation is based off gtk/gdk's method for distinguishing PEN/ERASER input source: https://gitlab.com/gnome/gtk/-/blob/master/gdk/x11/gdkdevicemanager-xi.c#L235. Personally, I don't like this method and would prefer to handle BTN_TOOL_PEN/BTN_TOOL_RUBBER events.

Relevant prototype commits:

  • hansemro/godot@a7f43e5
    • this is needed to get slave pointer id and name instead of Virtual core pointer with non-unique ids. Without this, all devices will have the same device id and name which will break this implementation.
    • when processing events, we can use sourceid to get slave pointer id to retrieve pen_inverted status for that device from a map.
  • hansemro/godot@2dff406

macOS

Check if pointingDeviceType is NSPointingDeviceTypeEraser only on NSEventSubtypeTabletProximity subtype event.

Relevant prototype commit: hansemro/godot@bc53003

Other Platforms

Android

  • Godot's Android input handler needs some work to properly support stylus input in general.

Check if event.getToolType(0) == MotionEvent.TOOL_TYPE_ERASER.

https://source.android.com/devices/accessories/stylus
https://developer.android.com/reference/android/view/MotionEvent.html#TOOL_TYPE_ERASER

iOS

Cannot be implemented.

HTML5

TODO

Testing

Godot demo project to test functionality: https://github.com/hansemro/InvertedPenGodotTest

If this enhancement will not be used often, can it be worked around with a few lines of script?

Although this feature may not be used often, it cannot easily be worked around as different platforms handle pen inversion differently.

Is there a reason why this should be core and not an add-on in the asset library?

This feature will fill a hole in the already-existing pen/tablet/wacom support. This feature could also help distinguish Godot from other engines.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions