Bug 831781 - Add support for ouya gamepad joystick-based scrolling. r=Cwiiis

This commit is contained in:
Kartikaya Gupta 2013-03-01 22:50:48 -05:00
parent 10b74a82f0
commit 543ebc67f2
2 changed files with 70 additions and 3 deletions

View File

@ -135,7 +135,7 @@ abstract class Axis {
private boolean mDisableSnap; /* Whether overscroll snapping is disabled. */
private float mDisplacement;
private FlingStates mFlingState; /* The fling state we're in on this axis. */
private FlingStates mFlingState = FlingStates.STOPPED; /* The fling state we're in on this axis. */
protected abstract float getOrigin();
protected abstract float getViewportLength();
@ -339,7 +339,7 @@ abstract class Axis {
if (mFlingState == FlingStates.PANNING)
mDisplacement += (mLastTouchPos - mTouchPos) * getEdgeResistance(false);
else
mDisplacement += mVelocity;
mDisplacement += mVelocity * getEdgeResistance(false);
// if overscroll is disabled and we're trying to overscroll, reset the displacement
// to remove any excess. Using getExcess alone isn't enough here since it relies on
@ -361,4 +361,12 @@ abstract class Axis {
mDisplacement = 0.0f;
return d;
}
void setAutoscrollVelocity(float velocity) {
if (mFlingState != FlingStates.STOPPED) {
Log.e(LOGTAG, "Setting autoscroll velocity while in a fling is not allowed!");
return;
}
mVelocity = velocity;
}
}

View File

@ -81,6 +81,9 @@ class JavaPanZoomController
WAITING_LISTENERS, /* a state halfway between NOTHING and TOUCHING - the user has
put a finger down, but we don't yet know if a touch listener has
prevented the default actions yet. we still need to abort animations. */
AUTOSCROLL, /* We are scrolling using an AutoscrollRunnable animation. This is similar
to the FLING state except that it must be stopped manually by the code that
started it, and it's velocity can be updated while it's running. */
}
private final PanZoomTarget mTarget;
@ -229,6 +232,11 @@ class JavaPanZoomController
case MotionEvent.ACTION_SCROLL: return handlePointerScroll(event);
}
break;
case InputDevice.SOURCE_CLASS_JOYSTICK:
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_MOVE: return handleJoystickScroll(event);
}
break;
}
return false;
}
@ -340,6 +348,7 @@ class JavaPanZoomController
mTarget.forceRedraw();
// fall through
case FLING:
case AUTOSCROLL:
case BOUNCE:
case NOTHING:
case WAITING_LISTENERS:
@ -362,6 +371,7 @@ class JavaPanZoomController
switch (mState) {
case FLING:
case AUTOSCROLL:
case BOUNCE:
case WAITING_LISTENERS:
// should never happen
@ -409,6 +419,7 @@ class JavaPanZoomController
switch (mState) {
case FLING:
case AUTOSCROLL:
case BOUNCE:
case WAITING_LISTENERS:
// should never happen
@ -473,6 +484,43 @@ class JavaPanZoomController
return false;
}
private float normalizeJoystick(float value, InputDevice.MotionRange range) {
// The 1e-2 here should really be range.getFlat() + range.getFuzz() but the
// values those functions return on the Ouya are zero so we're just hard-coding
// it for now.
if (Math.abs(value) < 1e-2) {
return 0;
}
// joystick axis positions are already normalized to [-1, 1] so just scale it up by how much we want
return value * MAX_SCROLL;
}
// Since this event is a position-based event rather than a motion-based event, we need to
// set up an AUTOSCROLL animation to keep scrolling even while we don't get events.
private boolean handleJoystickScroll(MotionEvent event) {
float velocityX = normalizeJoystick(event.getX(0), event.getDevice().getMotionRange(MotionEvent.AXIS_X));
float velocityY = normalizeJoystick(event.getY(0), event.getDevice().getMotionRange(MotionEvent.AXIS_Y));
if (velocityX == 0 && velocityY == 0) {
if (mState == PanZoomState.AUTOSCROLL) {
bounce(); // if not needed, this will automatically go to state NOTHING
return true;
}
return false;
}
if (mState == PanZoomState.NOTHING) {
setState(PanZoomState.AUTOSCROLL);
startAnimationTimer(new AutoscrollRunnable());
}
if (mState == PanZoomState.AUTOSCROLL) {
mX.setAutoscrollVelocity(velocityX);
mY.setAutoscrollVelocity(velocityY);
return true;
}
return false;
}
private void startTouch(float x, float y, long time) {
mX.startTouch(x);
mY.startTouch(y);
@ -597,7 +645,7 @@ class JavaPanZoomController
/* Starts the fling or bounce animation. */
private void startAnimationTimer(final AnimationRunnable runnable) {
if (mAnimationTimer != null) {
Log.e(LOGTAG, "Attempted to start a new fling without canceling the old one!");
Log.e(LOGTAG, "Attempted to start a new timer without canceling the old one!");
stopAnimationTimer();
}
@ -680,6 +728,17 @@ class JavaPanZoomController
}
}
private class AutoscrollRunnable extends AnimationRunnable {
protected void animateFrame() {
if (mState != PanZoomState.AUTOSCROLL) {
finishAnimation();
return;
}
updatePosition();
}
}
/* The callback that performs the bounce animation. */
private class BounceRunnable extends AnimationRunnable {
/* The current frame of the bounce-back animation */