Add API to get/set carousel rotation angle.

+ Add setCarouselRotationAngle
+ onAnimationFinished now returns the current carouselRotationAngle

+ remove Request/ReportFirstCardPositon, not required.

Note that the carouselRotationAngle is specified in floating point
slot positions, not radians or degrees.

Change-Id: I4f70c2aff07e9ab15a9bf6ac834ac5a61830a28b
diff --git a/carousel/java/com/android/ex/carousel/CarouselController.java b/carousel/java/com/android/ex/carousel/CarouselController.java
index 669acd9..139ba14 100644
--- a/carousel/java/com/android/ex/carousel/CarouselController.java
+++ b/carousel/java/com/android/ex/carousel/CarouselController.java
@@ -67,6 +67,7 @@
     private boolean mDrawCardsWithBlending = true;
     private boolean mDrawRuler = true;
     private float mStartAngle;
+    private float mCarouselRotationAngle;
     private float mRadius = DEFAULT_RADIUS;
     private float mCardRotation = 0.0f;
     private boolean mCardsFaceTangent = false;
@@ -111,6 +112,7 @@
         setBackgroundBitmap(mBackgroundBitmap);
         setDetailLineBitmap(mDefaultLineBitmap);
         setStartAngle(mStartAngle);
+        setCarouselRotationAngle(mCarouselRotationAngle);
         setRadius(mRadius);
         setCardRotation(mCardRotation);
         setCardsFaceTangent(mCardsFaceTangent);
@@ -462,6 +464,23 @@
         }
     }
 
+    /**
+     * Set the current carousel rotation angle, in card units.
+     * This is measured in card positions, not in radians or degrees.
+     *
+     * A value of 0.0 means that card 0 is in the home position.
+     * A value of 1.0 means that card 1 is in the home position, and so on.
+     * The maximum value will be somewhat less than the total number of cards.
+     *
+     * @param angle
+     */
+    public void setCarouselRotationAngle(float angle) {
+        mCarouselRotationAngle = angle;
+        if (mRenderScript != null) {
+            mRenderScript.setCarouselRotationAngle(angle);
+        }
+    }
+
     public void setRadius(float radius) {
         mRadius = radius;
         if (mRenderScript != null) {
@@ -513,12 +532,6 @@
         }
     }
 
-    public void requestFirstCardPosition() {
-        if (mRenderScript != null) {
-            mRenderScript.requestFirstCardPosition();
-        }
-    }
-
     /**
      * This sets the number of cards in the distance that will be shown "rezzing in".
      * These alpha values will be faded in from the background to the foreground over
diff --git a/carousel/java/com/android/ex/carousel/CarouselRS.java b/carousel/java/com/android/ex/carousel/CarouselRS.java
index 57e1852..6f62bb6 100644
--- a/carousel/java/com/android/ex/carousel/CarouselRS.java
+++ b/carousel/java/com/android/ex/carousel/CarouselRS.java
@@ -44,7 +44,6 @@
     public static final int CMD_ANIMATION_FINISHED = 500;
     public static final int CMD_REQUEST_DETAIL_TEXTURE = 600;
     public static final int CMD_INVALIDATE_DETAIL_TEXTURE = 610;
-    public static final int CMD_REPORT_FIRST_CARD_POSITION = 700;
     public static final int CMD_PING = 1000; // for debugging
 
     private static final String TAG = "CarouselRS";
@@ -146,13 +145,9 @@
 
         /**
          * Called when card animation has stopped.
+         * @param startAngle the angle of rotation, in radians, at which the animation stopped.
          */
-        void onAnimationFinished();
-
-        /**
-         * Called when the current position has been requested.
-         */
-        void onReportFirstCardPosition(int n);
+        void onAnimationFinished(float carouselRotationAngle);
     };
 
     private RSMessage mRsMessage = new RSMessage() {
@@ -199,11 +194,7 @@
                     break;
 
                 case CMD_ANIMATION_FINISHED:
-                    mCallback.onAnimationFinished();
-                    break;
-
-                case CMD_REPORT_FIRST_CARD_POSITION:
-                    mCallback.onReportFirstCardPosition(mData[0]);
+                    mCallback.onAnimationFinished(Float.intBitsToFloat(mData[0]));
                     break;
 
                 case CMD_PING:
@@ -231,6 +222,7 @@
         setVisibleSlots(DEFAULT_VISIBLE_SLOTS);
         createCards(DEFAULT_CARD_COUNT);
         setStartAngle(0.0f);
+        setCarouselRotationAngle(0.0f);
         setRadius(1.0f);
         setLookAt(mEyePoint, mAtPoint, mUp);
         setRadius(20.0f);
@@ -417,6 +409,10 @@
         mScript.set_startAngle(theta);
     }
 
+    public void setCarouselRotationAngle(float theta) {
+        mScript.invoke_setCarouselRotationAngle(theta);
+    }
+
     public void setCallback(CarouselCallback callback)
     {
         mCallback = callback;
@@ -586,10 +582,6 @@
         mScript.set_slotCount(n);
     }
 
-    public void requestFirstCardPosition() {
-        mScript.invoke_requestFirstCardPosition();
-    }
-
     public void setRezInCardCount(float alpha) {
         mScript.set_rezInCardCount(alpha);
     }
diff --git a/carousel/java/com/android/ex/carousel/CarouselView.java b/carousel/java/com/android/ex/carousel/CarouselView.java
index 4d0fcbf..062f250 100644
--- a/carousel/java/com/android/ex/carousel/CarouselView.java
+++ b/carousel/java/com/android/ex/carousel/CarouselView.java
@@ -76,6 +76,7 @@
     private boolean mDrawCardsWithBlending = true;
     private boolean mDrawRuler = true;
     private float mStartAngle;
+    private float mCarouselRotationAngle;
     private float mRadius = DEFAULT_RADIUS;
     private float mCardRotation = 0.0f;
     private boolean mCardsFaceTangent = false;
@@ -160,6 +161,7 @@
         setBackgroundBitmap(mBackgroundBitmap);
         setDetailLineBitmap(mDefaultLineBitmap);
         setStartAngle(mStartAngle);
+        setCarouselRotationAngle(mCarouselRotationAngle);
         setRadius(mRadius);
         setCardRotation(mCardRotation);
         setCardsFaceTangent(mCardsFaceTangent);
@@ -510,6 +512,23 @@
         }
     }
 
+    /**
+     * Set the current carousel rotation angle, in card units.
+     * This is measured in card positions, not in radians or degrees.
+     *
+     * A value of 0.0 means that card 0 is in the home position.
+     * A value of 1.0 means that card 1 is in the home position, and so on.
+     * The maximum value will be somewhat less than the total number of cards.
+     *
+     * @param angle
+     */
+    public void setCarouselRotationAngle(float angle) {
+        mCarouselRotationAngle = angle;
+        if (mRenderScript != null) {
+            mRenderScript.setCarouselRotationAngle(angle);
+        }
+    }
+
     public void setRadius(float radius) {
         mRadius = radius;
         if (mRenderScript != null) {
@@ -561,12 +580,6 @@
         }
     }
 
-    public void requestFirstCardPosition() {
-        if (mRenderScript != null) {
-            mRenderScript.requestFirstCardPosition();
-        }
-    }
-
     /**
      * This sets the number of cards in the distance that will be shown "rezzing in".
      * These alpha values will be faded in from the background to the foreground over
diff --git a/carousel/java/com/android/ex/carousel/CarouselViewHelper.java b/carousel/java/com/android/ex/carousel/CarouselViewHelper.java
index 927db93..cda60b6 100644
--- a/carousel/java/com/android/ex/carousel/CarouselViewHelper.java
+++ b/carousel/java/com/android/ex/carousel/CarouselViewHelper.java
@@ -260,11 +260,7 @@
 
     }
 
-    public void onAnimationFinished() {
-
-    }
-
-    public void onReportFirstCardPosition(int n) {
+    public void onAnimationFinished(float startAngle) {
 
     }
 
diff --git a/carousel/java/com/android/ex/carousel/MVCCarouselView.java b/carousel/java/com/android/ex/carousel/MVCCarouselView.java
index bf093c5..5d7573d 100644
--- a/carousel/java/com/android/ex/carousel/MVCCarouselView.java
+++ b/carousel/java/com/android/ex/carousel/MVCCarouselView.java
@@ -423,10 +423,6 @@
         mController.setLookAt(eye, at, up);
     }
 
-    public void requestFirstCardPosition() {
-        mController.requestFirstCardPosition();
-    }
-
     /**
      * This sets the number of cards in the distance that will be shown "rezzing in".
      * These alpha values will be faded in from the background to the foreground over
diff --git a/carousel/java/com/android/ex/carousel/MVCCarouselViewHelper.java b/carousel/java/com/android/ex/carousel/MVCCarouselViewHelper.java
index 30aec51..419797f 100644
--- a/carousel/java/com/android/ex/carousel/MVCCarouselViewHelper.java
+++ b/carousel/java/com/android/ex/carousel/MVCCarouselViewHelper.java
@@ -260,7 +260,7 @@
 
     }
 
-    public void onAnimationFinished() {
+    public void onAnimationFinished(float carouselRotationAngle) {
 
     }
 
diff --git a/carousel/java/com/android/ex/carousel/carousel.rs b/carousel/java/com/android/ex/carousel/carousel.rs
index d30b65b..193cba2 100644
--- a/carousel/java/com/android/ex/carousel/carousel.rs
+++ b/carousel/java/com/android/ex/carousel/carousel.rs
@@ -75,7 +75,6 @@
 static const int CMD_ANIMATION_FINISHED = 500;
 static const int CMD_REQUEST_DETAIL_TEXTURE = 600;
 static const int CMD_INVALIDATE_DETAIL_TEXTURE = 610;
-static const int CMD_REPORT_FIRST_CARD_POSITION = 700;
 static const int CMD_PING = 1000;
 
 // Constants
@@ -136,7 +135,7 @@
 #pragma rs export_func(createCards, copyCards, lookAt)
 #pragma rs export_func(doStart, doStop, doMotion, doLongPress, doSelection)
 #pragma rs export_func(setTexture, setGeometry, setDetailTexture, debugCamera, debugPicking)
-#pragma rs export_func(requestFirstCardPosition)
+#pragma rs export_func(setCarouselRotationAngle)
 
 // Local variables
 static float bias; // rotation bias, in radians. Used for animation and dragging.
@@ -145,7 +144,6 @@
 float4 backgroundColor;
 static const float FLT_MAX = 1.0e37;
 static int currentSelection = -1;
-static int currentFirstCard = -1;
 static int64_t touchTime = -1;  // time of first touch (see doStart())
 static float touchBias = 0.0f; // bias on first touch
 static float velocity = 0.0f;  // angular velocity in radians/s
@@ -320,6 +318,19 @@
     return cards * 2.0f * M_PI / slotCount;
 }
 
+// convert from carousel rotation angle (in card slot units) to radians.
+static float carouselRotationAngleToRadians(float carouselRotationAngle)
+{
+    return -wedgeAngle(carouselRotationAngle);
+}
+
+// convert from radians to carousel rotation angle (in card slot units).
+static float radiansToCarouselRotationAngle(float angle)
+{
+    return -angle * slotCount / ( 2.0f * M_PI );
+}
+
+
 // Return the lowest slot number for a given angular position.
 static int cardIndex(float angle)
 {
@@ -415,14 +426,8 @@
         cards[n].geometryState = STATE_INVALID;
 }
 
-void requestFirstCardPosition()
-{
-    int data[1];
-    data[0] = currentFirstCard;
-    bool enqueued = rsSendToClient(CMD_REPORT_FIRST_CARD_POSITION, data, sizeof(data));
-    if (!enqueued) {
-        rsDebug("Couldn't send CMD_REPORT_FIRST_CARD_POSITION", 0);
-    }
+void setCarouselRotationAngle(float carouselRotationAngle) {
+    bias = carouselRotationAngleToRadians(carouselRotationAngle);
 }
 
 static float3 getAnimatedScaleForSelected()
@@ -788,13 +793,19 @@
     return -1;
 }
 
+void sendAnimationFinished() {
+    float data[1];
+    data[0] = radiansToCarouselRotationAngle(bias);
+    rsSendToClient(CMD_ANIMATION_FINISHED, (int*) data, sizeof(data));
+}
+
 void doStart(float x, float y)
 {
     lastPosition.x = x;
     lastPosition.y = y;
     velocity = 0.0f;
     if (animating) {
-        rsSendToClient(CMD_ANIMATION_FINISHED);
+        sendAnimationFinished();
         animating = false;
         currentSelection = -1;
     } else {
@@ -1061,7 +1072,7 @@
 
         animating = fabs(velocity) > velocityThreshold;
         if (!animating) {
-            rsSendToClient(CMD_ANIMATION_FINISHED);
+            sendAnimationFinished();
         }
     }
     lastTime = currentTime;
@@ -1095,15 +1106,11 @@
     const float thetaLast = slotPosition(visibleSlotCount - 1 + prefetchCardCountPerSide);
 
     int count = 0;
-    int firstVisible = -1;
     for (int i = 0; i < cardCount; i++) {
         if (visibleSlotCount > 0) {
             // If visibleSlotCount is specified, then only show up to visibleSlotCount cards.
             float p = cardPosition(i);
             if (p >= thetaFirst && p < thetaLast) {
-                if (firstVisible == -1 && p >= thetaSelectedLow && p < thetaSelectedHigh) {
-                    firstVisible = i;
-                }
                 cards[i].visible = true;
                 count++;
             } else {
@@ -1116,7 +1123,6 @@
             count++;
         }
     }
-    currentFirstCard = firstVisible;
     return count;
 }