From 390ec125dcc1fe828fd4dfbdca638a8efb3a8248 Mon Sep 17 00:00:00 2001 From: Julien Pauty Date: Sat, 1 Dec 2018 17:21:05 +0100 Subject: [PATCH] Adding support for horizontal scrolling (touch pad and touch screen) Also, adding support for devices which report fractional scrolling amounts. E.g. a mouse with a continuous mouse wheel, or a Mac touch pad. This is currently only supported in lwjgl3. It can probably be added to android and maybe to gwt. InputProcessor scrolled method now receives scroll amount for X and Y. Changed type to float to support devices which report fractional scroll amounts. Updated InputEvent in scene2d accordingly: added scrollAmountX, scrollAmountY attributes and corresponding setters and getters. Input event queue can receive float scrolling values. Since the queue stores the events with integers. Scrolling values are stored in fixed precision format, with 8 bits for the fraction. Updated backends accordingly: lwjgl, lwjgl3, android and gwt. --- CHANGES | 2 ++ .../gdx/backends/android/AndroidInput.java | 5 +++-- .../backends/android/AndroidMouseHandler.java | 15 ++++++++----- .../gdx/backends/lwjgl/LwjglAWTInput.java | 2 +- .../gdx/backends/lwjgl/LwjglInput.java | 2 +- .../gdx/backends/lwjgl3/Lwjgl3Input.java | 20 +---------------- .../badlogic/gdx/backends/gwt/GwtInput.java | 2 +- .../tools/particleeditor/ParticleEditor.java | 2 +- gdx/src/com/badlogic/gdx/InputAdapter.java | 2 +- gdx/src/com/badlogic/gdx/InputEventQueue.java | 9 ++++---- .../com/badlogic/gdx/InputMultiplexer.java | 4 ++-- gdx/src/com/badlogic/gdx/InputProcessor.java | 5 +++-- .../g3d/utils/CameraInputController.java | 4 ++-- .../com/badlogic/gdx/input/RemoteSender.java | 2 +- .../gdx/scenes/scene2d/InputEvent.java | 22 +++++++++++++------ .../gdx/scenes/scene2d/InputListener.java | 4 ++-- .../badlogic/gdx/scenes/scene2d/Stage.java | 5 +++-- .../gdx/scenes/scene2d/ui/ScrollPane.java | 11 +++++----- 18 files changed, 58 insertions(+), 60 deletions(-) diff --git a/CHANGES b/CHANGES index a4313a9b695..107a0df7449 100755 --- a/CHANGES +++ b/CHANGES @@ -59,6 +59,8 @@ - API Addition: Added Group#removeActorAt(int,boolean) to avoid looking up the actor index. Subclasses intending to take action when an actor is removed may need to override this new method. - API Change: If Group#addActorAfter is called with an afterActor not in the group, the actor is added as the last child (not the first). +[1.9.10] +- API Change: InputProcessor scrolled method now receives scroll amount for X and Y. Changed type to float to support devices which report fractional scroll amounts. Updated InputEvent in scene2d accordingly: added scrollAmountX, scrollAmountY attributes and corresponding setters and getters. [1.9.9] - API Addition: Add support for stripping whitespace in PixmapPacker - API Addition: Add support for 9 patch packing in PixmapPacker diff --git a/backends/gdx-backend-android/src/com/badlogic/gdx/backends/android/AndroidInput.java b/backends/gdx-backend-android/src/com/badlogic/gdx/backends/android/AndroidInput.java index 89e3593838b..31694525cf6 100644 --- a/backends/gdx-backend-android/src/com/badlogic/gdx/backends/android/AndroidInput.java +++ b/backends/gdx-backend-android/src/com/badlogic/gdx/backends/android/AndroidInput.java @@ -76,7 +76,8 @@ static class TouchEvent { int type; int x; int y; - int scrollAmount; + int scrollAmountX; + int scrollAmountY; int button; int pointer; } @@ -412,7 +413,7 @@ void processEvents () { processor.mouseMoved(e.x, e.y); break; case TouchEvent.TOUCH_SCROLLED: - processor.scrolled(e.scrollAmount); + processor.scrolled(e.scrollAmountX, e.scrollAmountY); } usedTouchEvents.free(e); } diff --git a/backends/gdx-backend-android/src/com/badlogic/gdx/backends/android/AndroidMouseHandler.java b/backends/gdx-backend-android/src/com/badlogic/gdx/backends/android/AndroidMouseHandler.java index 668574df7c9..94f7b3c7b90 100644 --- a/backends/gdx-backend-android/src/com/badlogic/gdx/backends/android/AndroidMouseHandler.java +++ b/backends/gdx-backend-android/src/com/badlogic/gdx/backends/android/AndroidMouseHandler.java @@ -38,7 +38,8 @@ public boolean onGenericMotion (MotionEvent event, AndroidInput input) { final int action = event.getAction() & MotionEvent.ACTION_MASK; int x = 0, y = 0; - int scrollAmount = 0; + int scrollAmountX = 0; + int scrollAmountY = 0; long timeStamp = System.nanoTime(); synchronized (input) { @@ -47,15 +48,16 @@ public boolean onGenericMotion (MotionEvent event, AndroidInput input) { x = (int)event.getX(); y = (int)event.getY(); if ((x != deltaX) || (y != deltaY)) { // Avoid garbage events - postTouchEvent(input, TouchEvent.TOUCH_MOVED, x, y, 0, timeStamp); + postTouchEvent(input, TouchEvent.TOUCH_MOVED, x, y, 0, 0, timeStamp); deltaX = x; deltaY = y; } break; case MotionEvent.ACTION_SCROLL: - scrollAmount = (int)-Math.signum(event.getAxisValue(MotionEvent.AXIS_VSCROLL)); - postTouchEvent(input, TouchEvent.TOUCH_SCROLLED, 0, 0, scrollAmount, timeStamp); + scrollAmountY = (int)-Math.signum(event.getAxisValue(MotionEvent.AXIS_VSCROLL)); + scrollAmountX = (int)-Math.signum(event.getAxisValue(MotionEvent.AXIS_HSCROLL)); + postTouchEvent(input, TouchEvent.TOUCH_SCROLLED, 0, 0, scrollAmountX, scrollAmountY, timeStamp); } } @@ -78,13 +80,14 @@ else if (action == MotionEvent.ACTION_SCROLL) Gdx.app.log("AndroidMouseHandler", "action " + actionStr); } - private void postTouchEvent (AndroidInput input, int type, int x, int y, int scrollAmount, long timeStamp) { + private void postTouchEvent (AndroidInput input, int type, int x, int y, int scrollAmountX, int scrollAmountY, long timeStamp) { TouchEvent event = input.usedTouchEvents.obtain(); event.timeStamp = timeStamp; event.x = x; event.y = y; event.type = type; - event.scrollAmount = scrollAmount; + event.scrollAmountX = scrollAmountX; + event.scrollAmountY = scrollAmountY; input.touchEvents.add(event); } diff --git a/backends/gdx-backend-lwjgl/src/com/badlogic/gdx/backends/lwjgl/LwjglAWTInput.java b/backends/gdx-backend-lwjgl/src/com/badlogic/gdx/backends/lwjgl/LwjglAWTInput.java index 8aaf7ae8834..a38515a2351 100644 --- a/backends/gdx-backend-lwjgl/src/com/badlogic/gdx/backends/lwjgl/LwjglAWTInput.java +++ b/backends/gdx-backend-lwjgl/src/com/badlogic/gdx/backends/lwjgl/LwjglAWTInput.java @@ -383,7 +383,7 @@ void processEvents () { processor.mouseMoved(e.x, e.y); break; case TouchEvent.TOUCH_SCROLLED: - processor.scrolled(e.scrollAmount); + processor.scrolled(0, e.scrollAmount); break; } usedTouchEvents.free(e); diff --git a/backends/gdx-backend-lwjgl/src/com/badlogic/gdx/backends/lwjgl/LwjglInput.java b/backends/gdx-backend-lwjgl/src/com/badlogic/gdx/backends/lwjgl/LwjglInput.java index e1a139fff5d..75283fef306 100644 --- a/backends/gdx-backend-lwjgl/src/com/badlogic/gdx/backends/lwjgl/LwjglInput.java +++ b/backends/gdx-backend-lwjgl/src/com/badlogic/gdx/backends/lwjgl/LwjglInput.java @@ -366,7 +366,7 @@ void processEvents () { processor.mouseMoved(e.x, e.y); break; case TouchEvent.TOUCH_SCROLLED: - processor.scrolled(e.scrollAmount); + processor.scrolled(0,e.scrollAmount); } usedTouchEvents.free(e); } diff --git a/backends/gdx-backend-lwjgl3/src/com/badlogic/gdx/backends/lwjgl3/Lwjgl3Input.java b/backends/gdx-backend-lwjgl3/src/com/badlogic/gdx/backends/lwjgl3/Lwjgl3Input.java index 160ba228502..0d2c520fbd6 100644 --- a/backends/gdx-backend-lwjgl3/src/com/badlogic/gdx/backends/lwjgl3/Lwjgl3Input.java +++ b/backends/gdx-backend-lwjgl3/src/com/badlogic/gdx/backends/lwjgl3/Lwjgl3Input.java @@ -93,25 +93,7 @@ public void invoke(long window, int codepoint) { @Override public void invoke(long window, double scrollX, double scrollY) { Lwjgl3Input.this.window.getGraphics().requestRendering(); - if (scrollYRemainder > 0 && scrollY < 0 || scrollYRemainder < 0 && scrollY > 0 || - TimeUtils.nanoTime() - lastScrollEventTime > pauseTime ) { - // fire a scroll event immediately: - // - if the scroll direction changes; - // - if the user did not move the wheel for more than 250ms - scrollYRemainder = 0; - int scrollAmount = (int)-Math.signum(scrollY); - eventQueue.scrolled(scrollAmount); - lastScrollEventTime = TimeUtils.nanoTime(); - } - else { - scrollYRemainder += scrollY; - while (Math.abs(scrollYRemainder) >= 1) { - int scrollAmount = (int)-Math.signum(scrollY); - eventQueue.scrolled(scrollAmount); - lastScrollEventTime = TimeUtils.nanoTime(); - scrollYRemainder += scrollAmount; - } - } + eventQueue.scrolled(-(float)scrollX, -(float)scrollY); } }; diff --git a/backends/gdx-backends-gwt/src/com/badlogic/gdx/backends/gwt/GwtInput.java b/backends/gdx-backends-gwt/src/com/badlogic/gdx/backends/gwt/GwtInput.java index d75daf7f87b..6610d883650 100644 --- a/backends/gdx-backends-gwt/src/com/badlogic/gdx/backends/gwt/GwtInput.java +++ b/backends/gdx-backends-gwt/src/com/badlogic/gdx/backends/gwt/GwtInput.java @@ -646,7 +646,7 @@ private void handleEvent (NativeEvent e) { } if (e.getType().equals(getMouseWheelEvent())) { if (processor != null) { - processor.scrolled((int)getMouseWheelVelocity(e)); + processor.scrolled(0,(int)getMouseWheelVelocity(e)); } this.currentEventTimeStamp = TimeUtils.nanoTime(); e.preventDefault(); diff --git a/extensions/gdx-tools/src/com/badlogic/gdx/tools/particleeditor/ParticleEditor.java b/extensions/gdx-tools/src/com/badlogic/gdx/tools/particleeditor/ParticleEditor.java index 3f72f652e2a..7960d7070a9 100644 --- a/extensions/gdx-tools/src/com/badlogic/gdx/tools/particleeditor/ParticleEditor.java +++ b/extensions/gdx-tools/src/com/badlogic/gdx/tools/particleeditor/ParticleEditor.java @@ -599,7 +599,7 @@ public boolean mouseMoved (int x, int y) { } @Override - public boolean scrolled (int amount) { + public boolean scrolled (float amountX, float amountY) { return false; } diff --git a/gdx/src/com/badlogic/gdx/InputAdapter.java b/gdx/src/com/badlogic/gdx/InputAdapter.java index 737c36f5e91..b4bc28bb51f 100644 --- a/gdx/src/com/badlogic/gdx/InputAdapter.java +++ b/gdx/src/com/badlogic/gdx/InputAdapter.java @@ -50,7 +50,7 @@ public boolean mouseMoved (int screenX, int screenY) { } @Override - public boolean scrolled (int amount) { + public boolean scrolled (float amountX, float amountY) { return false; } } diff --git a/gdx/src/com/badlogic/gdx/InputEventQueue.java b/gdx/src/com/badlogic/gdx/InputEventQueue.java index 68252e930a8..492a4ad163c 100644 --- a/gdx/src/com/badlogic/gdx/InputEventQueue.java +++ b/gdx/src/com/badlogic/gdx/InputEventQueue.java @@ -92,7 +92,7 @@ public void drain () { localProcessor.mouseMoved(q[i++], q[i++]); break; case SCROLLED: - localProcessor.scrolled(q[i++]); + localProcessor.scrolled(q[i++] / 256f, q[i++] / 256f); break; default: throw new RuntimeException(); @@ -133,7 +133,7 @@ private synchronized int next (int nextType, int i) { i += 2; break; case SCROLLED: - i++; + i += 2; break; default: throw new RuntimeException(); @@ -218,10 +218,11 @@ public synchronized boolean mouseMoved (int screenX, int screenY) { return false; } - public synchronized boolean scrolled (int amount) { + public synchronized boolean scrolled(float amountX, float amountY) { queue.add(SCROLLED); queueTime(); - queue.add(amount); + queue.add((int)(amountX * 256)); + queue.add((int)(amountY * 256)); return false; } diff --git a/gdx/src/com/badlogic/gdx/InputMultiplexer.java b/gdx/src/com/badlogic/gdx/InputMultiplexer.java index 960ab8359da..24dacb57753 100644 --- a/gdx/src/com/badlogic/gdx/InputMultiplexer.java +++ b/gdx/src/com/badlogic/gdx/InputMultiplexer.java @@ -150,11 +150,11 @@ public boolean mouseMoved (int screenX, int screenY) { return false; } - public boolean scrolled (int amount) { + public boolean scrolled (float amountX,float amountY) { Object[] items = processors.begin(); try { for (int i = 0, n = processors.size; i < n; i++) - if (((InputProcessor)items[i]).scrolled(amount)) return true; + if (((InputProcessor)items[i]).scrolled(amountX, amountY)) return true; } finally { processors.end(); } diff --git a/gdx/src/com/badlogic/gdx/InputProcessor.java b/gdx/src/com/badlogic/gdx/InputProcessor.java index 28fb72d5a7d..8ee441355b0 100644 --- a/gdx/src/com/badlogic/gdx/InputProcessor.java +++ b/gdx/src/com/badlogic/gdx/InputProcessor.java @@ -67,7 +67,8 @@ public interface InputProcessor { public boolean mouseMoved (int screenX, int screenY); /** Called when the mouse wheel was scrolled. Will not be called on iOS. - * @param amount the scroll amount, -1 or 1 depending on the direction the wheel was scrolled. + * @param amountX the horizontal scroll amount, negative or positive depending on the direction the wheel was scrolled. + * @param amountY the vertical scroll amount, negative or positive depending on the direction the wheel was scrolled. * @return whether the input was processed. */ - public boolean scrolled (int amount); + public boolean scrolled (float amountX, float amountY); } diff --git a/gdx/src/com/badlogic/gdx/graphics/g3d/utils/CameraInputController.java b/gdx/src/com/badlogic/gdx/graphics/g3d/utils/CameraInputController.java index 34a0f9086eb..e6c4096e885 100644 --- a/gdx/src/com/badlogic/gdx/graphics/g3d/utils/CameraInputController.java +++ b/gdx/src/com/badlogic/gdx/graphics/g3d/utils/CameraInputController.java @@ -203,8 +203,8 @@ public boolean touchDragged (int screenX, int screenY, int pointer) { } @Override - public boolean scrolled (int amount) { - return zoom(amount * scrollFactor * translateUnits); + public boolean scrolled (float amountX, float amountY) { + return zoom(amountY * scrollFactor * translateUnits); } public boolean zoom (float amount) { diff --git a/gdx/src/com/badlogic/gdx/input/RemoteSender.java b/gdx/src/com/badlogic/gdx/input/RemoteSender.java index 148fe9780b5..eebb99926b9 100644 --- a/gdx/src/com/badlogic/gdx/input/RemoteSender.java +++ b/gdx/src/com/badlogic/gdx/input/RemoteSender.java @@ -198,7 +198,7 @@ public boolean mouseMoved (int x, int y) { } @Override - public boolean scrolled (int amount) { + public boolean scrolled (float amountX, float amountY) { return false; } diff --git a/gdx/src/com/badlogic/gdx/scenes/scene2d/InputEvent.java b/gdx/src/com/badlogic/gdx/scenes/scene2d/InputEvent.java index 83bc4ca68d8..ea8b97b4ddf 100644 --- a/gdx/src/com/badlogic/gdx/scenes/scene2d/InputEvent.java +++ b/gdx/src/com/badlogic/gdx/scenes/scene2d/InputEvent.java @@ -24,8 +24,8 @@ * @see InputListener */ public class InputEvent extends Event { private Type type; - private float stageX, stageY; - private int pointer, button, keyCode, scrollAmount; + private float stageX, stageY, scrollAmountX, scrollAmountY; + private int pointer, button, keyCode; private char character; @Null private Actor relatedActor; @@ -100,13 +100,21 @@ public void setCharacter (char character) { this.character = character; } - /** The amount the mouse was scrolled. Valid for: scrolled. */ - public int getScrollAmount () { - return scrollAmount; + /** The amount the mouse was scrolled horizontally. Valid for: scrolled. */ + public float getScrollAmountX () { + return scrollAmountX; + } + /** The amount the mouse was scrolled vertically. Valid for: scrolled. */ + public float getScrollAmountY () { + return scrollAmountY; + } + + public void setScrollAmountX (float scrollAmount) { + this.scrollAmountX = scrollAmount; } - public void setScrollAmount (int scrollAmount) { - this.scrollAmount = scrollAmount; + public void setScrollAmountY (float scrollAmount) { + this.scrollAmountY = scrollAmount; } /** The actor related to the event. Valid for: enter and exit. For enter, this is the actor being exited, or null. For exit, diff --git a/gdx/src/com/badlogic/gdx/scenes/scene2d/InputListener.java b/gdx/src/com/badlogic/gdx/scenes/scene2d/InputListener.java index 1744a741bf0..679cee96b55 100644 --- a/gdx/src/com/badlogic/gdx/scenes/scene2d/InputListener.java +++ b/gdx/src/com/badlogic/gdx/scenes/scene2d/InputListener.java @@ -65,7 +65,7 @@ public boolean handle (Event e) { case mouseMoved: return mouseMoved(event, tmpCoords.x, tmpCoords.y); case scrolled: - return scrolled(event, tmpCoords.x, tmpCoords.y, event.getScrollAmount()); + return scrolled(event, tmpCoords.x, tmpCoords.y, event.getScrollAmountX(), event.getScrollAmountY()); case enter: enter(event, tmpCoords.x, tmpCoords.y, event.getPointer(), event.getRelatedActor()); return false; @@ -119,7 +119,7 @@ public void exit (InputEvent event, float x, float y, int pointer, @Null Actor t } /** Called when the mouse wheel has been scrolled. When true is returned, the event is {@link Event#handle() handled}. */ - public boolean scrolled (InputEvent event, float x, float y, int amount) { + public boolean scrolled (InputEvent event, float x, float y, float amountX, float amountY) { return false; } diff --git a/gdx/src/com/badlogic/gdx/scenes/scene2d/Stage.java b/gdx/src/com/badlogic/gdx/scenes/scene2d/Stage.java index 0db6ac7d6e5..16d24a0eb66 100644 --- a/gdx/src/com/badlogic/gdx/scenes/scene2d/Stage.java +++ b/gdx/src/com/badlogic/gdx/scenes/scene2d/Stage.java @@ -387,7 +387,7 @@ public boolean mouseMoved (int screenX, int screenY) { /** Applies a mouse scroll event to the stage and returns true if an actor in the scene {@link Event#handle() handled} the * event. This event only occurs on the desktop. */ - public boolean scrolled (int amount) { + public boolean scrolled (float amountX, float amountY) { Actor target = scrollFocus == null ? root : scrollFocus; screenToStageCoordinates(tempCoords.set(mouseScreenX, mouseScreenY)); @@ -395,7 +395,8 @@ public boolean scrolled (int amount) { InputEvent event = Pools.obtain(InputEvent.class); event.setStage(this); event.setType(InputEvent.Type.scrolled); - event.setScrollAmount(amount); + event.setScrollAmountX(amountX); + event.setScrollAmountY(amountY); event.setStageX(tempCoords.x); event.setStageY(tempCoords.y); target.fire(event); diff --git a/gdx/src/com/badlogic/gdx/scenes/scene2d/ui/ScrollPane.java b/gdx/src/com/badlogic/gdx/scenes/scene2d/ui/ScrollPane.java index fea7f06c7a3..b2fabfdd79a 100644 --- a/gdx/src/com/badlogic/gdx/scenes/scene2d/ui/ScrollPane.java +++ b/gdx/src/com/badlogic/gdx/scenes/scene2d/ui/ScrollPane.java @@ -214,13 +214,12 @@ public boolean handle (Event event) { addListener(flickScrollListener); addListener(new InputListener() { - public boolean scrolled (InputEvent event, float x, float y, int amount) { + public boolean scrolled (InputEvent event, float x, float y, float scrollAmountX, float scrollAmountY) { setScrollbarsVisible(true); - if (scrollY) - setScrollY(amountY + getMouseWheelY() * amount); - else if (scrollX) // - setScrollX(amountX + getMouseWheelX() * amount); - else + if (scrollY || scrollX) { + setScrollY(amountY + getMouseWheelY() * scrollAmountY); + setScrollX(amountX + getMouseWheelX() * scrollAmountX); + } else return false; return true; }