Skip to content

Commit

Permalink
Adding support for horizontal scrolling (touch pad and touch screen)
Browse files Browse the repository at this point in the history
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. Keeping the original scroll method of InputProcessor
for backward compatibility.  Updated InputEvent in scene2d
accordingly: added scrollAmountX, scrollAmountY attributes and
corresponding setters and getters.

Input event queue can receive float scrolling values.

Updated backends accordingly: lwjgl, lwjgl3, android and gwt.
  • Loading branch information
Julien Pauty committed Sep 12, 2020
1 parent a23543c commit 53190a8
Show file tree
Hide file tree
Showing 29 changed files with 76 additions and 81 deletions.
1 change: 1 addition & 0 deletions CHANGES
Expand Up @@ -33,6 +33,7 @@
- API Change: Enabling fullscreen mode on the lwjgl3 backend now automatically sets the vsync setting again.
- API Addition: Added put(key, value, defaultValue) for maps with primitive keys, so the old value can be returned.
- API Addition: Added ObjectLongMap.
- 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.11]
- Update to MobiVM 2.3.8
Expand Down
Expand Up @@ -35,7 +35,8 @@ public boolean onGenericMotion (MotionEvent event, DefaultAndroidInput 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) {
Expand All @@ -44,15 +45,16 @@ public boolean onGenericMotion (MotionEvent event, DefaultAndroidInput 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);

}
}
Expand All @@ -75,13 +77,14 @@ else if (action == MotionEvent.ACTION_SCROLL)
Gdx.app.log("AndroidMouseHandler", "action " + actionStr);
}

private void postTouchEvent (DefaultAndroidInput input, int type, int x, int y, int scrollAmount, long timeStamp) {
private void postTouchEvent (DefaultAndroidInput 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);
}

Expand Down
Expand Up @@ -77,7 +77,8 @@ static class TouchEvent {
int type;
int x;
int y;
int scrollAmount;
int scrollAmountX;
int scrollAmountY;
int button;
int pointer;
}
Expand Down Expand Up @@ -419,7 +420,7 @@ public 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);
}
Expand Down
Expand Up @@ -367,7 +367,7 @@ public 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);
}
Expand Down
Expand Up @@ -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);
Expand Down
Expand Up @@ -87,31 +87,10 @@ public void invoke(long window, int codepoint) {
};

private GLFWScrollCallback scrollCallback = new GLFWScrollCallback() {
private long pauseTime = 250000000L; //250ms
private float scrollYRemainder;
private long lastScrollEventTime;
@Override
public void invoke(long window, double scrollX, double scrollY) {
DefaultLwjgl3Input.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);
}
};

Expand Down
Expand Up @@ -715,7 +715,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();
Expand Down
Expand Up @@ -350,11 +350,11 @@ public OrthoCamController (OrthographicCamera camera) {
}

@Override
public boolean scrolled (int amount) {
worldCamera.zoom += amount * 0.01f;
public boolean scrolled (float amountX, float amountY) {
worldCamera.zoom += amountY * 0.01f;
worldCamera.zoom = MathUtils.clamp(worldCamera.zoom, 0.01f, 5000);
worldCamera.update();
return super.scrolled(amount);
return super.scrolled(amountX, amountY);
}

@Override
Expand Down Expand Up @@ -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;
}

Expand Down
2 changes: 1 addition & 1 deletion gdx/src/com/badlogic/gdx/InputAdapter.java
Expand Up @@ -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;
}
}
10 changes: 6 additions & 4 deletions gdx/src/com/badlogic/gdx/InputEventQueue.java
Expand Up @@ -18,6 +18,7 @@

import com.badlogic.gdx.utils.IntArray;
import com.badlogic.gdx.utils.TimeUtils;
import com.badlogic.gdx.utils.NumberUtils;

/** Queues events that are later passed to the wrapped {@link InputProcessor}.
* @author Nathan Sweet */
Expand Down Expand Up @@ -92,7 +93,7 @@ public void drain () {
localProcessor.mouseMoved(q[i++], q[i++]);
break;
case SCROLLED:
localProcessor.scrolled(q[i++]);
localProcessor.scrolled(NumberUtils.intBitsToFloat(q[i++]) , NumberUtils.intBitsToFloat(q[i++]));
break;
default:
throw new RuntimeException();
Expand Down Expand Up @@ -133,7 +134,7 @@ private synchronized int next (int nextType, int i) {
i += 2;
break;
case SCROLLED:
i++;
i += 2;
break;
default:
throw new RuntimeException();
Expand Down Expand Up @@ -218,10 +219,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(NumberUtils.floatToIntBits(amountX));
queue.add(NumberUtils.floatToIntBits(amountY));
return false;
}

Expand Down
4 changes: 2 additions & 2 deletions gdx/src/com/badlogic/gdx/InputMultiplexer.java
Expand Up @@ -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();
}
Expand Down
5 changes: 3 additions & 2 deletions gdx/src/com/badlogic/gdx/InputProcessor.java
Expand Up @@ -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);
}
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion gdx/src/com/badlogic/gdx/input/RemoteSender.java
Expand Up @@ -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;
}

Expand Down
22 changes: 15 additions & 7 deletions gdx/src/com/badlogic/gdx/scenes/scene2d/InputEvent.java
Expand Up @@ -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;
private @Null Actor relatedActor;
private boolean touchFocus = true;
Expand Down Expand Up @@ -103,13 +103,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,
Expand Down
4 changes: 2 additions & 2 deletions gdx/src/com/badlogic/gdx/scenes/scene2d/InputListener.java
Expand Up @@ -74,7 +74,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;
Expand Down Expand Up @@ -128,7 +128,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;
}

Expand Down
5 changes: 3 additions & 2 deletions gdx/src/com/badlogic/gdx/scenes/scene2d/Stage.java
Expand Up @@ -386,15 +386,16 @@ 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));

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);
Expand Down
11 changes: 5 additions & 6 deletions gdx/src/com/badlogic/gdx/scenes/scene2d/ui/ScrollPane.java
Expand Up @@ -208,13 +208,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;
}
Expand Down
Expand Up @@ -121,7 +121,7 @@ public boolean mouseMoved (int x, int y) {
}

@Override
public boolean scrolled (int amount) {
public boolean scrolled (float amountX, float amountY) {
return false;
}

Expand Down
Expand Up @@ -162,8 +162,8 @@ public boolean mouseMoved (int x, int y) {
}

@Override
public boolean scrolled (int amount) {
return tests[testIndex].scrolled(amount);
public boolean scrolled (float amountX, float amountY) {
return tests[testIndex].scrolled(amountX, amountY);
}

@Override
Expand Down
4 changes: 2 additions & 2 deletions tests/gdx-tests/src/com/badlogic/gdx/tests/InputTest.java
Expand Up @@ -109,8 +109,8 @@ public boolean mouseMoved (int x, int y) {
}

@Override
public boolean scrolled (int amount) {
Gdx.app.log("Input Test", "scrolled: " + amount);
public boolean scrolled (float amountX, float amountY) {
Gdx.app.log("Input Test", "scrolled: " + amountY);
return false;
}

Expand Down
Expand Up @@ -119,9 +119,9 @@ public void changed (ChangeEvent event, Actor actor) {
stage.addActor(table);

Gdx.input.setInputProcessor(new InputMultiplexer(new InputAdapter() {
public boolean scrolled (int amount) {
public boolean scrolled (float amountX, float amountY) {
if (!Gdx.input.isKeyPressed(Keys.CONTROL_LEFT)) return false;
duration -= amount / 15f;
duration -= amountY / 15f;
duration = MathUtils.clamp(duration, 0, Float.POSITIVE_INFINITY);
return true;
}
Expand Down
Expand Up @@ -93,7 +93,7 @@ public boolean mouseMoved (int x, int y) {
}

@Override
public boolean scrolled (int amount) {
public boolean scrolled (float amountX, float amountY) {
// TODO Auto-generated method stub
return false;
}
Expand Down

0 comments on commit 53190a8

Please sign in to comment.