summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnaud Berry <arnaudberry@google.com>2011-02-07 18:25:43 -0800
committerArnaud Berry <arnaudberry@google.com>2011-02-07 18:25:43 -0800
commit8debeb8a0a785f0ad66bc75200cdb47c137602bc (patch)
tree77f8e42349b2608c1196a045ad003a32a41f1803
parent42813c328294b3355b7986f1c5987302132e7da1 (diff)
downloadandroid_frameworks_ex-8debeb8a0a785f0ad66bc75200cdb47c137602bc.tar.gz
android_frameworks_ex-8debeb8a0a785f0ad66bc75200cdb47c137602bc.tar.bz2
android_frameworks_ex-8debeb8a0a785f0ad66bc75200cdb47c137602bc.zip
Added a way to trigger an interpolated rotation of the carousel
Change-Id: I4717952f5fe6b5d99699e55d93abcd1cb1fc1986
-rw-r--r--carousel/java/com/android/ex/carousel/CarouselController.java23
-rw-r--r--carousel/java/com/android/ex/carousel/CarouselRS.java6
-rw-r--r--carousel/java/com/android/ex/carousel/CarouselView.java12
-rw-r--r--carousel/java/com/android/ex/carousel/carousel.rs108
4 files changed, 148 insertions, 1 deletions
diff --git a/carousel/java/com/android/ex/carousel/CarouselController.java b/carousel/java/com/android/ex/carousel/CarouselController.java
index 7516250..cd29f68 100644
--- a/carousel/java/com/android/ex/carousel/CarouselController.java
+++ b/carousel/java/com/android/ex/carousel/CarouselController.java
@@ -606,6 +606,29 @@ public class CarouselController {
}
}
+ /**
+ * Triggers a rotation of the carousel. All angles are in card units, see:
+ * {@link CarouselController#setCarouselRotationAngle(float)}) for more details.
+ *
+ * @param endAngle the card unit to which the carousel should rotate to
+ * @param milliseconds the length of the animation
+ * @param interpolationMode three modes are currently supported :
+ * {@link CarouselView.InterpolationMode#LINEAR}
+ * {@link CarouselView.InterpolationMode#DECELERATE_QUADRATIC}
+ * {@link CarouselView.InterpolationMode#ACCELERATE_DECELERATE_CUBIC}
+ * @param maxAnimatedArc the maximum angular distance over which the transition will be
+ * animated.
+ * If the current position is further away, it is set at maxAnimatedArc from endAngle.
+ * This parameter is ignored when <= 0.
+ */
+ public void setCarouselRotationAngle(float endAngle, int milliseconds, int interpolationMode,
+ float maxAnimatedArc) {
+ if (mRenderScript != null) {
+ mRenderScript.setCarouselRotationAngle(endAngle, milliseconds,
+ interpolationMode, maxAnimatedArc);
+ }
+ }
+
public void setRadius(float radius) {
mRadius = radius;
if (mRenderScript != null) {
diff --git a/carousel/java/com/android/ex/carousel/CarouselRS.java b/carousel/java/com/android/ex/carousel/CarouselRS.java
index 4467fb3..6ab4811 100644
--- a/carousel/java/com/android/ex/carousel/CarouselRS.java
+++ b/carousel/java/com/android/ex/carousel/CarouselRS.java
@@ -631,6 +631,12 @@ public class CarouselRS {
mScript.invoke_setCarouselRotationAngle(theta);
}
+ public void setCarouselRotationAngle(float endAngle, int milliseconds, int interpolationMode,
+ float maxAnimatedArc) {
+ mScript.invoke_setCarouselRotationAngle2(endAngle, milliseconds, interpolationMode,
+ maxAnimatedArc);
+ }
+
public void setCallback(CarouselCallback callback)
{
mCallback = callback;
diff --git a/carousel/java/com/android/ex/carousel/CarouselView.java b/carousel/java/com/android/ex/carousel/CarouselView.java
index 6fd0f20..235387b 100644
--- a/carousel/java/com/android/ex/carousel/CarouselView.java
+++ b/carousel/java/com/android/ex/carousel/CarouselView.java
@@ -62,6 +62,18 @@ public abstract class CarouselView extends RSSurfaceView {
public static final int FILL_DIRECTION_CW = CarouselRS.FILL_DIRECTION_CW;
// Note: remember to update carousel.rs when changing the values below
+ public static class InterpolationMode {
+ /** y= x **/
+ public static final int LINEAR = 0;
+ /** The quadratic curve y= 1 - (1 - x)^2 moves quickly towards the target
+ * while decelerating constantly. **/
+ public static final int DECELERATE_QUADRATIC = 1;
+ /** The cubic curve y= (3-2x)*x^2 gradually accelerates at the origin,
+ * and decelerates near the target. **/
+ public static final int ACCELERATE_DECELERATE_CUBIC = 2;
+ }
+
+ // Note: remember to update carousel.rs when changing the values below
public static class DetailAlignment {
/** Detail is centered vertically with respect to the card **/
public static final int CENTER_VERTICAL = 1;
diff --git a/carousel/java/com/android/ex/carousel/carousel.rs b/carousel/java/com/android/ex/carousel/carousel.rs
index ae6d1fc..807c101 100644
--- a/carousel/java/com/android/ex/carousel/carousel.rs
+++ b/carousel/java/com/android/ex/carousel/carousel.rs
@@ -84,6 +84,13 @@ enum {
STATE_LOADED // item was delivered
};
+// Interpolation modes ** THIS LIST MUST MATCH THOSE IN CarouselView.java ***
+enum {
+ INTERPOLATION_LINEAR = 0,
+ INTERPOLATION_DECELERATE_QUADRATIC = 1,
+ INTERPOLATION_ACCELERATE_DECELERATE_CUBIC = 2,
+};
+
// Detail texture alignments ** THIS LIST MUST MATCH THOSE IN CarouselView.java ***
enum {
/** Detail is centered vertically with respect to the card **/
@@ -215,6 +222,7 @@ static float touchBias = 0.0f; // bias on first touch
static float2 touchPosition; // position of first touch, as defined by last call to doStart(x,y)
static float velocity = 0.0f; // angular velocity in radians/s
static bool overscroll = false; // whether we're in the overscroll animation
+static bool autoscrolling = false; // whether we're in the autoscroll animation
static bool isDragging = false; // true while the user is dragging the carousel
static float selectionRadius = 50.0f; // movement greater than this will result in no selection
static bool enableSelection = false; // enabled until the user drags outside of selectionRadius
@@ -266,6 +274,7 @@ static bool __attribute__((overloadable))
static float deltaTimeInSeconds(int64_t current);
static bool rayPlaneIntersect(Ray* ray, Plane* plane, float* tout);
static bool rayCylinderIntersect(Ray* ray, Cylinder* cylinder, float* tout);
+static void stopAutoscroll();
void init() {
// initializers currently have a problem when the variables are exported, so initialize
@@ -1090,6 +1099,7 @@ void doStart(float x, float y, long eventTime)
isDragging = true;
overscroll = false;
animatedSelection = doSelection(x, y); // used to provide visual feedback on touch
+ stopAutoscroll();
}
void doStop(float x, float y, long eventTime)
@@ -1175,6 +1185,100 @@ void doMotion(float x, float y, long eventTime)
}
////////////////////////////////////////////////////////////////////////////////////////////////////
+// Autoscroll Interpolation
+////////////////////////////////////////////////////////////////////////////////////////////////////
+static int64_t autoscrollStartTime = 0L; //tracks when we actually started interpolating
+static int64_t autoscrollDuration = 0L; //in milli seconds
+static int autoscrollInterpolationMode = INTERPOLATION_LINEAR;
+
+static float autoscrollStopAngle = 0.0f;
+static float autoscrollStartAngle = 0.0f;
+
+void setCarouselRotationAngle2(
+ float endAngle,
+ int milliseconds,
+ int interpolationMode,
+ float maxAnimatedArc)
+{
+ float actualStart = radiansToCarouselRotationAngle(bias);
+
+ if (maxAnimatedArc > 0) {
+ //snap the current position to keep end - start under maxAnimatedArc
+ if (actualStart <= endAngle) {
+ if (actualStart < endAngle - maxAnimatedArc) {
+ actualStart = endAngle - maxAnimatedArc;
+ }
+ }
+ else {
+ if (actualStart > endAngle + maxAnimatedArc) {
+ actualStart = endAngle + maxAnimatedArc;
+ }
+ }
+ }
+
+ animating = true;
+ autoscrolling = true;
+ autoscrollDuration = milliseconds;
+ autoscrollInterpolationMode = interpolationMode;
+ autoscrollStartAngle = carouselRotationAngleToRadians(actualStart);
+ autoscrollStopAngle = carouselRotationAngleToRadians(endAngle);
+
+ //Make sure the start and stop angles are in the allowed range
+ const float highBias = maximumBias();
+ const float lowBias = minimumBias();
+ autoscrollStartAngle = clamp(autoscrollStartAngle, lowBias, highBias);
+ autoscrollStopAngle = clamp(autoscrollStopAngle, lowBias, highBias);
+
+ //stop other animation kinds
+ overscroll = false;
+ velocity = 0.0f;
+}
+
+static void stopAutoscroll()
+{
+ autoscrolling = false;
+ autoscrollStartTime = 0L; //reset for next time
+}
+
+// This method computes the position of all the cards by updating bias based on a
+// simple interpolation model. If the cards are still in motion, returns true.
+static bool doAutoscroll(float currentTime)
+{
+ if (autoscrollDuration == 0L) {
+ return false;
+ }
+
+ if (autoscrollStartTime == 0L) {
+ autoscrollStartTime = currentTime;
+ }
+
+ const int64_t interpolationEndTime = autoscrollStartTime + autoscrollDuration;
+
+ float timePos = (currentTime - autoscrollStartTime) / (float)autoscrollDuration;
+ if (timePos > 1.0f) {
+ timePos = 1.0f;
+ }
+
+ float lambda = timePos; //default to linear
+ if (autoscrollInterpolationMode == INTERPOLATION_DECELERATE_QUADRATIC) {
+ lambda = 1.0f - (1.0f - timePos) * (1.0f - timePos);
+ }
+ else if (autoscrollInterpolationMode == INTERPOLATION_ACCELERATE_DECELERATE_CUBIC) {
+ lambda = timePos * timePos * (3 - 2 * timePos);
+ }
+
+ bias = lambda * autoscrollStopAngle + (1.0 - lambda) * autoscrollStartAngle;
+
+ if (currentTime > interpolationEndTime) {
+ stopAutoscroll();
+ return false;
+ }
+ else {
+ return true;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
// Hit detection using ray casting.
////////////////////////////////////////////////////////////////////////////////////////////////////
static const float EPSILON = 1.0e-6f;
@@ -1424,7 +1528,7 @@ static float easeOut(float x)
return x;
}
-// Computes the next value for bias using the current animation (physics or overscroll)
+// Computes the next value for bias using the current animation (physics/overscroll/autoscrolling)
static bool updateNextPosition(int64_t currentTime)
{
static const float biasMin = 1e-4f; // close enough if we're within this margin of result
@@ -1457,6 +1561,8 @@ static bool updateNextPosition(int64_t currentTime)
} else {
overscroll = false;
}
+ } else if (autoscrolling) {
+ stillAnimating = doAutoscroll(currentTime);
} else {
stillAnimating = doPhysics(dt);
overscroll = bias > highBias || bias < lowBias;