From 87e428ec46ed5baefcfaf26475fe71d82c215817 Mon Sep 17 00:00:00 2001 From: Benjamin Amos Date: Tue, 2 Nov 2021 22:24:51 +0000 Subject: [PATCH] feat(nui-libgdx): replace touch pointer removal logic with configurable stickiness --- .../backends/libgdx/LibGDXMouseDevice.java | 40 ++++++++++++++----- 1 file changed, 29 insertions(+), 11 deletions(-) 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]--; + } + } } /**