Provide option to allow cards to face the center of the carousel circle.

Change-Id: I74ea4308316735ef5ec28318e4dc9374410894fa
diff --git a/carousel/java/com/android/ex/carousel/CarouselController.java b/carousel/java/com/android/ex/carousel/CarouselController.java
index ece628d..2d7a4f6 100644
--- a/carousel/java/com/android/ex/carousel/CarouselController.java
+++ b/carousel/java/com/android/ex/carousel/CarouselController.java
@@ -65,6 +65,7 @@
     private float mStartAngle;
     private float mRadius = DEFAULT_RADIUS;
     private float mCardRotation = 0.0f;
+    private boolean mCardsFaceTangent = false;
     private float mSwaySensitivity = DEFAULT_SWAY_SENSITIVITY;
     private float mFrictionCoefficient = DEFAULT_FRICTION_COEFFICIENT;
     private float mDragFactor = DEFAULT_DRAG_FACTOR;
@@ -107,6 +108,7 @@
         setStartAngle(mStartAngle);
         setRadius(mRadius);
         setCardRotation(mCardRotation);
+        setCardsFaceTangent(mCardsFaceTangent);
         setSwaySensitivity(mSwaySensitivity);
         setFrictionCoefficient(mFrictionCoefficient);
         setDragFactor(mDragFactor);
@@ -419,6 +421,13 @@
         }
     }
 
+    public void setCardsFaceTangent(boolean faceTangent) {
+        mCardsFaceTangent = faceTangent;
+        if (mRenderScript != null) {
+            mRenderScript.setCardsFaceTangent(faceTangent);
+        }
+    }
+
     public void setSwaySensitivity(float swaySensitivity) {
         mSwaySensitivity = swaySensitivity;
         if (mRenderScript != null) {
diff --git a/carousel/java/com/android/ex/carousel/CarouselRS.java b/carousel/java/com/android/ex/carousel/CarouselRS.java
index ad04048..66ff5d6 100644
--- a/carousel/java/com/android/ex/carousel/CarouselRS.java
+++ b/carousel/java/com/android/ex/carousel/CarouselRS.java
@@ -248,6 +248,10 @@
         mScript.set_cardRotation(cardRotation);
     }
 
+    public void setCardsFaceTangent(boolean faceTangent) {
+        mScript.set_cardsFaceTangent(faceTangent);
+    }
+
     public void setSwaySensitivity(float swaySensitivity) {
         mScript.set_swaySensitivity(swaySensitivity);
     }
diff --git a/carousel/java/com/android/ex/carousel/CarouselView.java b/carousel/java/com/android/ex/carousel/CarouselView.java
index 3aaa9fa..e8f40f8 100644
--- a/carousel/java/com/android/ex/carousel/CarouselView.java
+++ b/carousel/java/com/android/ex/carousel/CarouselView.java
@@ -73,6 +73,7 @@
     private float mStartAngle;
     private float mRadius = DEFAULT_RADIUS;
     private float mCardRotation = 0.0f;
+    private boolean mCardsFaceTangent = false;
     private float mSwaySensitivity = DEFAULT_SWAY_SENSITIVITY;
     private float mFrictionCoefficient = DEFAULT_FRICTION_COEFFICIENT;
     private float mDragFactor = DEFAULT_DRAG_FACTOR;
@@ -142,6 +143,7 @@
         setStartAngle(mStartAngle);
         setRadius(mRadius);
         setCardRotation(mCardRotation);
+        setCardsFaceTangent(mCardsFaceTangent);
         setSwaySensitivity(mSwaySensitivity);
         setFrictionCoefficient(mFrictionCoefficient);
         setDragFactor(mDragFactor);
@@ -455,6 +457,13 @@
         }
     }
 
+    public void setCardsFaceTangent(boolean faceTangent) {
+        mCardsFaceTangent = faceTangent;
+        if (mRenderScript != null) {
+          mRenderScript.setCardsFaceTangent(faceTangent);
+        }
+    }
+
     public void setSwaySensitivity(float swaySensitivity) {
         mSwaySensitivity = swaySensitivity;
         if (mRenderScript != null) {
diff --git a/carousel/java/com/android/ex/carousel/MVCCarouselView.java b/carousel/java/com/android/ex/carousel/MVCCarouselView.java
index a2c95b5..f1e0def 100644
--- a/carousel/java/com/android/ex/carousel/MVCCarouselView.java
+++ b/carousel/java/com/android/ex/carousel/MVCCarouselView.java
@@ -342,6 +342,10 @@
         mController.setCardRotation(cardRotation);
     }
 
+    public void setCardsFaceTangent(boolean faceTangent) {
+        mController.setCardsFaceTangent(faceTangent);
+    }
+
     public void setSwaySensitivity(float swaySensitivity) {
         mController.setSwaySensitivity(swaySensitivity);
     }
diff --git a/carousel/java/com/android/ex/carousel/carousel.rs b/carousel/java/com/android/ex/carousel/carousel.rs
index 3435463..6890120 100644
--- a/carousel/java/com/android/ex/carousel/carousel.rs
+++ b/carousel/java/com/android/ex/carousel/carousel.rs
@@ -102,6 +102,7 @@
 bool drawRuler; // whether to draw a ruler from the card to the detail texture
 float radius; // carousel radius. Cards will be centered on a circle with this radius
 float cardRotation; // rotation of card in XY plane relative to Z=1
+bool cardsFaceTangent; // whether cards are rotated to face along a tangent to the circle
 float swaySensitivity; // how much to rotate cards in relation to the rotation velocity
 float frictionCoeff; // how much to slow down the carousel over time
 float dragFactor; // a scale factor for how sensitive the carousel is to user dragging
@@ -126,7 +127,7 @@
 rs_sampler linearClamp;
 
 #pragma rs export_var(radius, cards, tmpCards, slotCount, visibleSlotCount, cardRotation, backgroundColor)
-#pragma rs export_var(swaySensitivity, frictionCoeff, dragFactor)
+#pragma rs export_var(cardsFaceTangent, swaySensitivity, frictionCoeff, dragFactor)
 #pragma rs export_var(visibleDetailCount, drawDetailBelowCard, drawRuler)
 #pragma rs export_var(programStore, vertexProgram, rasterProgram)
 #pragma rs export_var(singleTextureFragmentProgram, multiTextureFragmentProgram)
@@ -193,6 +194,7 @@
     bias = 0.0f;
     radius = 1.0f;
     cardRotation = 0.0f;
+    cardsFaceTangent = false;
     updateCamera = true;
     initialized = false;
     backgroundColor = (float4) { 0.0f, 0.0f, 0.0f, 1.0f };
@@ -461,7 +463,11 @@
     float swayAngle = getSwayAngleForVelocity(velocity, enableSway);
     rsMatrixRotate(matrix, degrees(theta), 0, 1, 0);
     rsMatrixTranslate(matrix, radius, 0, 0);
-    rsMatrixRotate(matrix, degrees(-theta + cardRotation + swayAngle), 0, 1, 0);
+    float rotation = cardRotation + swayAngle;
+    if (!cardsFaceTangent) {
+      rotation -= theta;
+    }
+    rsMatrixRotate(matrix, degrees(rotation), 0, 1, 0);
     if (i == currentSelection) {
         float3 scale = getAnimatedScaleForSelected();
         rsMatrixScale(matrix, scale.x, scale.y, scale.z);