diff --git a/nui-libgdx/src/main/java/org/terasology/nui/backends/libgdx/LibGDXMouseDevice.java b/nui-libgdx/src/main/java/org/terasology/nui/backends/libgdx/LibGDXMouseDevice.java index cddbccd1f..70ce020ac 100644 --- a/nui-libgdx/src/main/java/org/terasology/nui/backends/libgdx/LibGDXMouseDevice.java +++ b/nui-libgdx/src/main/java/org/terasology/nui/backends/libgdx/LibGDXMouseDevice.java @@ -31,6 +31,13 @@ public class LibGDXMouseDevice implements MouseDevice { // The maximum number of touches that LibGDX supports on Android is 20. // See https://github.com/libgdx/libgdx/blob/5eac848925d6e1f24070f887cbfaf99bb8bc4a63/backends/gdx-backend-android/src/com/badlogic/gdx/backends/android/AndroidInput.java#L99 private static final int MAX_POINTERS = 20; + // The default value has been calibrated by trial and error, mostly. You can set your own stickiness in the constructor. + private static final int DEFAULT_POINTER_STICKINESS = 4; + /** + * Defines how "sticky" a pointer is, meaning how many updates it should be retained for after the touch is released. + * This value can be fine-tuned based on the desired general responsiveness of the UI. + */ + private final int pointerStickiness; /** * Flags a pointer for "removal" when it is no longer present on the screen. * @@ -43,11 +50,20 @@ public class LibGDXMouseDevice implements MouseDevice { * The removePointer variable is used to delay this removal by a single update, so that UI widgets have time * to register the removal first (e.g. for button de-presses). */ - private boolean[] removePointer; + private final int[] pointerCooldowns; public LibGDXMouseDevice() { + this(DEFAULT_POINTER_STICKINESS); + } + + /** + * @param pointerStickiness Defines how "sticky" a pointer is, + * meaning how many updates it should be retained for after the touch is released. + */ + public LibGDXMouseDevice(int pointerStickiness) { NUIInputProcessor.init(); - removePointer = new boolean[MAX_POINTERS]; + this.pointerStickiness = pointerStickiness; + pointerCooldowns = new int[MAX_POINTERS]; } @Override @@ -72,15 +88,12 @@ public Vector2i getPosition(int pointer) { if (Gdx.app.getType() == Application.ApplicationType.Android) { if (Gdx.input.isTouched(pointer)) { - removePointer[pointer] = false; - } else { - if (removePointer[pointer]) { - // Since touches are mapped to pointers on Android, reset the pointer when not currently touching. - // Set the pointer to an off-screen location, so it acts as if it were not present. - return new Vector2i(Integer.MAX_VALUE, Integer.MAX_VALUE); - } else { - removePointer[pointer] = true; - } + pointerCooldowns[pointer] = pointerStickiness; + } else if (pointerCooldowns[pointer] <= 0) { + pointerCooldowns[pointer] = 0; + // Since touches are mapped to pointers on Android, reset the pointer when not currently touching. + // Set the pointer to an off-screen location, so it acts as if it were not present. + return new Vector2i(Integer.MAX_VALUE, Integer.MAX_VALUE); } } @@ -106,6 +119,11 @@ public boolean isButtonDown(int button) { @Override public void update() { + for (int pointer = 0; pointer < MAX_POINTERS; pointer++) { + if (pointerCooldowns[pointer] > 0) { + pointerCooldowns[pointer]--; + } + } } /**