Home | History | Annotate | Download | only in carousel
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.ex.carousel;
     18 
     19 import com.android.ex.carousel.CarouselRS.CarouselCallback;
     20 import com.android.ex.carousel.CarouselView.DetailAlignment;
     21 
     22 import android.graphics.Bitmap;
     23 import android.renderscript.Float4;
     24 import android.renderscript.Mesh;
     25 import android.renderscript.RenderScriptGL;
     26 import android.util.Log;
     27 
     28 /**
     29  * <p>
     30  * This class represents the basic building block for using a 3D Carousel. The Carousel is
     31  * basically a scene of cards and slots.  The spacing between cards is dictated by the number
     32  * of slots and the radius. The number of visible cards dictates how far the Carousel can be moved.
     33  * If the number of cards exceeds the number of slots, then the Carousel will continue to go
     34  * around until the last card can be seen.
     35  */
     36 public class CarouselController {
     37     private final int DEFAULT_SLOT_COUNT = 10;
     38     private final float DEFAULT_RADIUS = 20.0f;
     39     private final int DEFAULT_VISIBLE_DETAIL_COUNT = 3;
     40     private final int DEFAULT_PREFETCH_CARD_COUNT = 2;
     41     private final int DEFAULT_ROW_COUNT = 1;
     42     private final float DEFAULT_OVERSCROLL_SLOTS = 1.0f;
     43     private final float DEFAULT_ROW_SPACING = 0.0f;
     44     private final float DEFAULT_SWAY_SENSITIVITY = 0.0f;
     45     private final float DEFAULT_FRICTION_COEFFICIENT = 10.0f;
     46     private final float DEFAULT_DRAG_FACTOR = 0.25f;
     47     private final int DEFAULT_DETAIL_ALIGNMENT =
     48             DetailAlignment.VIEW_TOP | DetailAlignment.LEFT;
     49     private CarouselRS mRenderScript;
     50     private RenderScriptGL mRS;
     51     private static final String TAG = "CarouselController";
     52     private static final boolean DBG = false;
     53 
     54     // These shadow the state of the renderer in case the surface changes so the surface
     55     // can be restored to its previous state.
     56     private Bitmap mDefaultBitmap;
     57     private Bitmap mLoadingBitmap;
     58     private Bitmap mBackgroundBitmap;
     59     private Bitmap mDefaultLineBitmap = Bitmap.createBitmap(
     60             new int[] {0x00000000, 0xffffffff, 0x00000000}, 0, 3, 3, 1, Bitmap.Config.ARGB_4444);
     61     private int mDefaultGeometry;
     62     private int mLoadingGeometry;
     63     private float[] mDefaultCardMatrix;
     64     private int mCardCount = 0;
     65     private int mVisibleSlots = 0;
     66     private int mVisibleDetails = DEFAULT_VISIBLE_DETAIL_COUNT;
     67     private int mPrefetchCardCount = DEFAULT_PREFETCH_CARD_COUNT;
     68     private int mDetailTextureAlignment = DEFAULT_DETAIL_ALIGNMENT;
     69     private boolean mForceBlendCardsWithZ = false;
     70     private boolean mDrawRuler = true;
     71     private float mStartAngle;
     72     private float mCarouselRotationAngle;
     73     private float mRadius = DEFAULT_RADIUS;
     74     private float mCardRotation = 0.0f;
     75     private boolean mCardsFaceTangent = false;
     76     private float mOverscrollSlots = DEFAULT_OVERSCROLL_SLOTS;
     77     private float mSwaySensitivity = DEFAULT_SWAY_SENSITIVITY;
     78     private float mFrictionCoefficient = DEFAULT_FRICTION_COEFFICIENT;
     79     private float mDragFactor = DEFAULT_DRAG_FACTOR;
     80     private int mSlotCount = DEFAULT_SLOT_COUNT;
     81     private int mRowCount = DEFAULT_ROW_COUNT;
     82     private float mRowSpacing = DEFAULT_ROW_SPACING;
     83     private float mEye[] = { 20.6829f, 2.77081f, 16.7314f };
     84     private float mAt[] = { 14.7255f, -3.40001f, -1.30184f };
     85     private float mUp[] = { 0.0f, 1.0f, 0.0f };
     86     private Float4 mBackgroundColor = new Float4(0.0f, 0.0f, 0.0f, 1.0f);
     87     private CarouselCallback mCarouselCallback;
     88     private float mRezInCardCount = 0.0f;
     89     private long mFadeInDuration = 250L;
     90     private long mCardCreationFadeDuration = 0L;
     91     private Bitmap mDetailLoadingBitmap = Bitmap.createBitmap(
     92             new int[] {0}, 0, 1, 1, 1, Bitmap.Config.ARGB_4444);
     93     private int mDragModel = CarouselRS.DRAG_MODEL_SCREEN_DELTA;
     94     private int mFillDirection = CarouselRS.FILL_DIRECTION_CCW;
     95     private boolean mFirstCardTop = false;
     96     private int[] mStoreConfigs;
     97 
     98     public CarouselController() {
     99         boolean useDepthBuffer = true;
    100     }
    101 
    102     public void setRS(RenderScriptGL rs, CarouselRS renderScript) {
    103         mRS = rs;
    104         mRenderScript = renderScript;
    105     }
    106 
    107     public void onSurfaceChanged() {
    108         setSlotCount(mSlotCount);
    109         setDefaultCardMatrix(mDefaultCardMatrix);
    110         createCards(mCardCount);
    111         setVisibleSlots(mVisibleSlots);
    112         setVisibleDetails(mVisibleDetails);
    113         setPrefetchCardCount(mPrefetchCardCount);
    114         setOverscrollSlots(mOverscrollSlots);
    115         setRowCount(mRowCount);
    116         setRowSpacing(mRowSpacing);
    117         setFirstCardTop(mFirstCardTop);
    118         setDetailTextureAlignment(mDetailTextureAlignment);
    119         setForceBlendCardsWithZ(mForceBlendCardsWithZ);
    120         setDrawRuler(mDrawRuler);
    121         setCallback(mCarouselCallback);
    122         setDefaultBitmap(mDefaultBitmap);
    123         setLoadingBitmap(mLoadingBitmap);
    124         setDefaultGeometry(mDefaultGeometry);
    125         setLoadingGeometry(mLoadingGeometry);
    126         setBackgroundColor(mBackgroundColor.x, mBackgroundColor.y, mBackgroundColor.z,
    127                 mBackgroundColor.w);
    128         setBackgroundBitmap(mBackgroundBitmap);
    129         setDetailLineBitmap(mDefaultLineBitmap);
    130         setStartAngle(mStartAngle);
    131         setCarouselRotationAngle(mCarouselRotationAngle);
    132         setRadius(mRadius);
    133         setCardRotation(mCardRotation);
    134         setCardsFaceTangent(mCardsFaceTangent);
    135         setSwaySensitivity(mSwaySensitivity);
    136         setFrictionCoefficient(mFrictionCoefficient);
    137         setDragFactor(mDragFactor);
    138         setDragModel(mDragModel);
    139         setFillDirection(mFillDirection);
    140         setLookAt(mEye, mAt, mUp);
    141         setRezInCardCount(mRezInCardCount);
    142         setFadeInDuration(mFadeInDuration);
    143         setCardCreationFadeDuration(mCardCreationFadeDuration);
    144         setDetailLoadingBitmap(mDetailLoadingBitmap);
    145         setStoreConfigs(mStoreConfigs);
    146     }
    147 
    148     /**
    149      * Loads geometry from a resource id.
    150      *
    151      * @param resId
    152      * @return the loaded mesh or null if it cannot be loaded
    153      */
    154     public Mesh loadGeometry(int resId) {
    155         if (mRenderScript != null) {
    156           return mRenderScript.loadGeometry(resId);
    157         }
    158         return null;
    159     }
    160 
    161     /**
    162      * Set the geometry to show for a given slot.
    163      * @param n The card to set the geometry for
    164      * @param mesh The geometry for that item
    165      * @see {@link #setDefaultGeometry}
    166      */
    167     public void setGeometryForItem(int n, Mesh mesh) {
    168         if (mRenderScript != null) {
    169             mRenderScript.setGeometry(n, mesh);
    170         }
    171     }
    172 
    173     /**
    174      * Load A3D file from resource. If resId == 0, will clear geometry for this item.
    175      * @param n The card to set the geometry for
    176      * @param resId The resource ID for the geometry for that item
    177      * @see {@link #setDefaultGeometry}
    178      */
    179     public void setGeometryForItem(int n, int resId) {
    180         if (mRenderScript != null) {
    181             Mesh mesh = mRenderScript.loadGeometry(resId);
    182             mRenderScript.setGeometry(n, mesh);
    183         }
    184     }
    185 
    186     /**
    187      * Set the matrix for the specified card
    188      * @param n The card to set the matrix for
    189      * @param matrix The matrix to use
    190      * @see {@link #setDefaultGeometry}
    191      */
    192     public void setMatrixForItem(int n, float[] matrix) {
    193         if (mRenderScript != null) {
    194             mRenderScript.setMatrix(n, matrix);
    195         }
    196     }
    197 
    198     /**
    199      * Set the number of slots around the Carousel. Basically equivalent to the poles horses
    200      * might attach to on a real Carousel.
    201      *
    202      * @param n the number of slots
    203      */
    204     public void setSlotCount(int n) {
    205         mSlotCount = n;
    206         if (mRenderScript != null) {
    207             mRenderScript.setSlotCount(n);
    208         }
    209     }
    210 
    211     /**
    212      * Sets the number of visible slots around the Carousel.  This is primarily used as a cheap
    213      * form of clipping. The Carousel will never show more than this many cards.
    214      * @param n the number of visible slots
    215      */
    216     public void setVisibleSlots(int n) {
    217         mVisibleSlots = n;
    218         if (mRenderScript != null) {
    219             mRenderScript.setVisibleSlots(n);
    220         }
    221     }
    222 
    223     /**
    224      * Set the number of detail textures that can be visible at one time.
    225      *
    226      * @param n the number of slots
    227      */
    228     public void setVisibleDetails(int n) {
    229         mVisibleDetails = n;
    230         if (mRenderScript != null) {
    231             mRenderScript.setVisibleDetails(n);
    232         }
    233     }
    234 
    235     /**
    236      * Set the number of cards to pre-load that are outside of the visible region, as determined by
    237      * setVisibleSlots(). This number gets added to the number of visible slots and used to
    238      * determine when resources for cards should be loaded. This number should be small (n <= 4)
    239      * for systems with limited texture memory or views that show more than half dozen cards in the
    240      * view.
    241      *
    242      * @param n the number of cards; should be even, so the count is the same on each side
    243      */
    244     public void setPrefetchCardCount(int n) {
    245         mPrefetchCardCount = n;
    246         if (mRenderScript != null) {
    247             mRenderScript.setPrefetchCardCount(n);
    248         }
    249     }
    250 
    251     /**
    252      * Sets the number of rows of cards to show in each slot.
    253      */
    254     public void setRowCount(int n) {
    255         mRowCount = n;
    256         if (mRenderScript != null) {
    257             mRenderScript.setRowCount(n);
    258         }
    259     }
    260 
    261     /**
    262      * Sets the spacing between each row of cards when rowCount > 1.
    263      */
    264     public void setRowSpacing(float s) {
    265         mRowSpacing = s;
    266         if (mRenderScript != null) {
    267             mRenderScript.setRowSpacing(s);
    268         }
    269     }
    270 
    271      /**
    272      * Sets the position of the first card when rowCount > 1 .
    273      */
    274     public void setFirstCardTop(boolean f) {
    275         mFirstCardTop = f;
    276         if (mRenderScript != null) {
    277             mRenderScript.setFirstCardTop(f);
    278         }
    279     }
    280 
    281     /**
    282      * Sets the amount of allowed overscroll (in slots)
    283      */
    284     public void setOverscrollSlots(float slots) {
    285         mOverscrollSlots = slots;
    286         if (mRenderScript != null) {
    287             mRenderScript.setOverscrollSlots(slots);
    288         }
    289     }
    290 
    291     /**
    292      * Sets how detail textures are aligned with respect to the card.
    293      *
    294      * @param alignment a bitmask of DetailAlignment flags.
    295      */
    296     public void setDetailTextureAlignment(int alignment) {
    297         int xBits = alignment & DetailAlignment.HORIZONTAL_ALIGNMENT_MASK;
    298         if (xBits == 0 || ((xBits & (xBits - 1)) != 0)) {
    299             throw new IllegalArgumentException(
    300                     "Must specify exactly one horizontal alignment flag");
    301         }
    302         int yBits = alignment & DetailAlignment.VERTICAL_ALIGNMENT_MASK;
    303         if (yBits == 0 || ((yBits & (yBits - 1)) != 0)) {
    304             throw new IllegalArgumentException(
    305                     "Must specify exactly one vertical alignment flag");
    306         }
    307 
    308         mDetailTextureAlignment = alignment;
    309         if (mRenderScript != null) {
    310             mRenderScript.setDetailTextureAlignment(alignment);
    311         }
    312     }
    313 
    314     /**
    315      * Set whether depth is enabled while blending. Generally, this is discouraged because
    316      * it causes bad artifacts. Careful attention to geometry and alpha transparency of
    317      * textures can mitigate much of this. Geometry for an individual item must be drawn
    318      * back-to-front, for example.
    319      *
    320      * @param enabled True to enable depth while blending, and false to disable it.
    321      */
    322     public void setForceBlendCardsWithZ(boolean enabled) {
    323         mForceBlendCardsWithZ = enabled;
    324         if (mRenderScript != null) {
    325             mRenderScript.setForceBlendCardsWithZ(enabled);
    326         }
    327     }
    328 
    329     /**
    330      * Set whether to draw a ruler from the card to the detail texture
    331      *
    332      * @param drawRuler True to draw a ruler, false to draw nothing where the ruler would go.
    333      */
    334     public void setDrawRuler(boolean drawRuler) {
    335         mDrawRuler = drawRuler;
    336         if (mRenderScript != null) {
    337             mRenderScript.setDrawRuler(drawRuler);
    338         }
    339     }
    340 
    341     /**
    342      * This dictates how many cards are in the deck.  If the number of cards is greater than the
    343      * number of slots, then the Carousel goes around n / slot_count times.
    344      *
    345      * Can be called again to increase or decrease the number of cards.
    346      *
    347      * @param n the number of cards to create.
    348      */
    349     public void createCards(int n) {
    350         mCardCount = n;
    351         if (mRenderScript != null) {
    352             mRenderScript.createCards(n);
    353         }
    354     }
    355 
    356     public int getCardCount() {
    357         return mCardCount;
    358     }
    359 
    360     /**
    361      * This sets the texture on card n.  It should only be called in response to
    362      * {@link CarouselCallback#onRequestTexture(int)}.  Since there's no guarantee
    363      * that a given texture is still on the screen, replacing this texture should be done
    364      * by first setting it to null and then waiting for the next
    365      * {@link CarouselCallback#onRequestTexture(int)} to swap it with the new one.
    366      *
    367      * @param n the card given by {@link CarouselCallback#onRequestTexture(int)}
    368      * @param bitmap the bitmap image to show
    369      */
    370     public void setTextureForItem(int n, Bitmap bitmap) {
    371         // Also check against mRS, to handle the case where the result is being delivered by a
    372         // background thread but the sender no longer exists.
    373         if (mRenderScript != null && mRS != null) {
    374             if (DBG) Log.v(TAG, "setTextureForItem(" + n + ")");
    375             mRenderScript.setTexture(n, bitmap);
    376             if (DBG) Log.v(TAG, "done");
    377         }
    378     }
    379 
    380     /**
    381      * This sets the detail texture that floats above card n. It should only be called in response
    382      * to {@link CarouselCallback#onRequestDetailTexture(int)}.  Since there's no guarantee
    383      * that a given texture is still on the screen, replacing this texture should be done
    384      * by first setting it to null and then waiting for the next
    385      * {@link CarouselCallback#onRequestDetailTexture(int)} to swap it with the new one.
    386      *
    387      * @param n the card to set detail texture for
    388      * @param offx an optional offset to apply to the texture (in pixels) from top of detail line
    389      * @param offy an optional offset to apply to the texture (in pixels) from top of detail line
    390      * @param loffx an optional offset to apply to the line (in pixels) from left edge of card
    391      * @param loffy an optional offset to apply to the line (in pixels) from top of screen
    392      * @param bitmap the bitmap to show as the detail
    393      */
    394     public void setDetailTextureForItem(int n, float offx, float offy, float loffx, float loffy,
    395             Bitmap bitmap) {
    396         if (mRenderScript != null && mRS != null) {
    397             if (DBG) Log.v(TAG, "setDetailTextureForItem(" + n + ")");
    398             mRenderScript.setDetailTexture(n, offx, offy, loffx, loffy, bitmap);
    399             if (DBG) Log.v(TAG, "done");
    400         }
    401     }
    402 
    403     /**
    404      * Sets the specified texture as invalid. If {@code eraseCurrent} is true,
    405      * the texture will be immediately cleared from view and an invalidate
    406      * handler will be called. If {@code eraseCurrent} is false, a replacement
    407      * texture will be requested, and the old texture will be left in place in
    408      * the meantime.
    409      *
    410      * @param n the card to invalidate the detail texture for
    411      * @param eraseCurrent whether to erase the current texture
    412      */
    413     public void invalidateTexture(int n, boolean eraseCurrent) {
    414         if (mRenderScript != null && mRS != null) {
    415             if (DBG) Log.v(TAG, "invalidateTexture(" + n + ", " + eraseCurrent + ")");
    416             mRenderScript.invalidateTexture(n, eraseCurrent);
    417             if (DBG) Log.v(TAG, "done");
    418         }
    419     }
    420 
    421     /**
    422      * Sets the specified detail texture as invalid. If eraseCurrent is true, the texture will be
    423      * immediately cleared from view and an invalidate handler will be called. If eraseCurrent is
    424      * false, a replacement texture will be requested, and the old texture will be left in place
    425      * in the meantime.
    426      * @param n the card to invalidate the detail texture for
    427      * @param eraseCurrent whether to erase the current texture
    428      */
    429     public void invalidateDetailTexture(int n, boolean eraseCurrent) {
    430         if (mRenderScript != null && mRS != null) {
    431             if (DBG) Log.v(TAG, "invalidateDetailTexture(" + n + ", " + eraseCurrent + ")");
    432             mRenderScript.invalidateDetailTexture(n, eraseCurrent);
    433             if (DBG) Log.v(TAG, "done");
    434         }
    435     }
    436 
    437     /**
    438      * Sets the bitmap to show on a card when the card draws the very first time.
    439      * Generally, this bitmap will only be seen during the first few frames of startup
    440      * or when the number of cards are changed.  It can be ignored in most cases,
    441      * as the cards will generally only be in the loading or loaded state.
    442      *
    443      * @param bitmap
    444      */
    445     public void setDefaultBitmap(Bitmap bitmap) {
    446         mDefaultBitmap = bitmap;
    447         if (mRenderScript != null) {
    448             mRenderScript.setDefaultBitmap(bitmap);
    449         }
    450     }
    451 
    452     /**
    453      * Sets the bitmap to show on the card while the texture is loading. It is set to this
    454      * value just before {@link CarouselCallback#onRequestTexture(int)} is called and changed
    455      * when {@link CarouselView#setTextureForItem(int, Bitmap)} is called. It is shared by all
    456      * cards.
    457      *
    458      * @param bitmap
    459      */
    460     public void setLoadingBitmap(Bitmap bitmap) {
    461         mLoadingBitmap = bitmap;
    462         if (mRenderScript != null) {
    463             mRenderScript.setLoadingBitmap(bitmap);
    464         }
    465     }
    466 
    467     /**
    468      * Sets background to specified color.  If a background texture is specified with
    469      * {@link CarouselView#setBackgroundBitmap(Bitmap)}, then this call has no effect.
    470      *
    471      * @param red the amount of red
    472      * @param green the amount of green
    473      * @param blue the amount of blue
    474      * @param alpha the amount of alpha
    475      */
    476     public void setBackgroundColor(float red, float green, float blue, float alpha) {
    477         mBackgroundColor = new Float4(red, green, blue, alpha);
    478         if (mRenderScript != null) {
    479             mRenderScript.setBackgroundColor(mBackgroundColor);
    480         }
    481     }
    482 
    483     /**
    484      * Can be used to optionally set the background to a bitmap. When set to something other than
    485      * null, this overrides {@link CarouselController#setBackgroundColor(Float4)}.
    486      *
    487      * @param bitmap
    488      */
    489     public void setBackgroundBitmap(Bitmap bitmap) {
    490         mBackgroundBitmap = bitmap;
    491         if (mRenderScript != null) {
    492             mRenderScript.setBackgroundTexture(bitmap);
    493         }
    494     }
    495 
    496     /**
    497      * Can be used to optionally set a "loading" detail bitmap. Typically, this is just a black
    498      * texture with alpha = 0 to allow details to slowly fade in.
    499      *
    500      * @param bitmap
    501      */
    502     public void setDetailLoadingBitmap(Bitmap bitmap) {
    503         mDetailLoadingBitmap = bitmap;
    504         if (mRenderScript != null) {
    505             mRenderScript.setDetailLoadingTexture(bitmap);
    506         }
    507     }
    508 
    509     /**
    510      * This texture is used to draw a line from the card alongside the texture detail. The line
    511      * will be as wide as the texture. It can be used to give the line glow effects as well as
    512      * allowing other blending effects. It is typically one dimensional, e.g. 3x1.
    513      *
    514      * @param bitmap
    515      */
    516     public void setDetailLineBitmap(Bitmap bitmap) {
    517         mDefaultLineBitmap = bitmap;
    518         if (mRenderScript != null) {
    519             mRenderScript.setDetailLineTexture(bitmap);
    520         }
    521     }
    522 
    523     /**
    524      * This geometry will be shown when no geometry has been loaded for a given slot. If not set,
    525      * a quad will be drawn in its place. It is shared for all cards. If something other than
    526      * simple planar geometry is used, consider enabling depth test with
    527      * {@link CarouselController#setForceBlendCardsWithZ(boolean)}
    528      *
    529      * @param mesh
    530      */
    531     public void setDefaultGeometry(int resId) {
    532         mDefaultGeometry = resId;
    533         if (mRenderScript != null) {
    534             Mesh mesh = mRenderScript.loadGeometry(resId);
    535             mRenderScript.setDefaultGeometry(mesh);
    536         }
    537     }
    538 
    539     /**
    540      * Sets the matrix used to transform card geometries.  By default, this
    541      * is the identity matrix, but you can specify a different matrix if you
    542      * want to scale, translate and / or rotate the card before drawing.
    543      *
    544      * @param matrix array of 9 or 16 floats representing a 3x3 or 4x4 matrix,
    545      * or null as a shortcut for an identity matrix.
    546      */
    547     public void setDefaultCardMatrix(float[] matrix) {
    548         mDefaultCardMatrix = matrix;
    549         if (mRenderScript != null) {
    550            mRenderScript.setDefaultCardMatrix(matrix);
    551         }
    552     }
    553 
    554     /**
    555      * This is an intermediate version of the object to show while geometry is loading. If not set,
    556      * a quad will be drawn in its place.  It is shared for all cards. If something other than
    557      * simple planar geometry is used, consider enabling depth test with
    558      * {@link CarouselView#setForceBlendCardsWithZ(boolean)}
    559      *
    560      * @param resId
    561      */
    562     public void setLoadingGeometry(int resId) {
    563         mLoadingGeometry = resId;
    564         if (mRenderScript != null) {
    565             Mesh mesh = mRenderScript.loadGeometry(resId);
    566             mRenderScript.setLoadingGeometry(mesh);
    567         }
    568     }
    569 
    570     /**
    571      * Sets the callback for receiving events from RenderScript.
    572      *
    573      * @param callback
    574      */
    575     public void setCallback(CarouselCallback callback)
    576     {
    577         mCarouselCallback = callback;
    578         if (mRenderScript != null) {
    579             mRenderScript.setCallback(callback);
    580         }
    581     }
    582 
    583     /**
    584      * Gets the callback for receiving events from Renderscript.
    585      */
    586     public CarouselCallback getCallback() {
    587         return mCarouselCallback;
    588     }
    589 
    590     /**
    591      * Sets the startAngle for the Carousel. The start angle is the first position of the first
    592      * slot draw.  Cards will be drawn from this angle in a counter-clockwise manner around the
    593      * Carousel.
    594      *
    595      * @param angle the angle, in radians.
    596      */
    597     public void setStartAngle(float angle)
    598     {
    599         mStartAngle = angle;
    600         if (mRenderScript != null) {
    601             mRenderScript.setStartAngle(angle);
    602         }
    603     }
    604 
    605     /**
    606      * Set the current carousel rotation angle, in card units.
    607      * This is measured in card positions, not in radians or degrees.
    608      *
    609      * A value of 0.0 means that card 0 is in the home position.
    610      * A value of 1.0 means that card 1 is in the home position, and so on.
    611      * The maximum value will be somewhat less than the total number of cards.
    612      *
    613      * @param angle
    614      */
    615     public void setCarouselRotationAngle(float angle) {
    616         mCarouselRotationAngle = angle;
    617         if (mRenderScript != null) {
    618             mRenderScript.setCarouselRotationAngle(angle);
    619         }
    620     }
    621 
    622     /**
    623      * Triggers a rotation of the carousel. All angles are in card units, see:
    624      * {@link CarouselController#setCarouselRotationAngle(float)}) for more details.
    625      *
    626      * @param endAngle the card unit to which the carousel should rotate to
    627      * @param milliseconds the length of the animation
    628      * @param interpolationMode three modes are currently supported :
    629      * {@link CarouselView.InterpolationMode#LINEAR}
    630      * {@link CarouselView.InterpolationMode#DECELERATE_QUADRATIC}
    631      * {@link CarouselView.InterpolationMode#ACCELERATE_DECELERATE_CUBIC}
    632      * @param maxAnimatedArc the maximum angular distance over which the transition will be
    633      * animated.
    634      * If the current position is further away, it is set at maxAnimatedArc from endAngle.
    635      * This parameter is ignored when <= 0.
    636      */
    637     public void setCarouselRotationAngle(float endAngle, int milliseconds, int interpolationMode,
    638             float maxAnimatedArc) {
    639         if (mRenderScript != null) {
    640             mRenderScript.setCarouselRotationAngle(endAngle, milliseconds,
    641                     interpolationMode, maxAnimatedArc);
    642         }
    643     }
    644 
    645     public void setRadius(float radius) {
    646         mRadius = radius;
    647         if (mRenderScript != null) {
    648             mRenderScript.setRadius(radius);
    649         }
    650     }
    651 
    652     /**
    653      * Sets the current model for dragging. There are currently four drag models:
    654      * {@link CarouselView#DRAG_MODEL_SCREEN_DELTA}
    655      * {@link CarouselView#DRAG_MODEL_PLANE}
    656      * {@link CarouselView#DRAG_MODEL_CYLINDER_INSIDE}
    657      * {@link CarouselView#DRAG_MODEL_CYLINDER_OUTSIDE}
    658      *
    659      * @param model
    660      */
    661     public void setDragModel(int model) {
    662         mDragModel  = model;
    663         if (mRenderScript != null) {
    664             mRenderScript.setDragModel(model);
    665         }
    666     }
    667 
    668     /** Sets the direction to fill in cards around the carousel.
    669      *
    670      * @param direction Either {@link CarouselRS#FILL_DIRECTION_CCW} or
    671      * {@link CarouselRS#FILL_DIRECTION_CW}.
    672      */
    673     public void setFillDirection(int direction) {
    674         mFillDirection = direction;
    675         if (mRenderScript != null) {
    676             mRenderScript.setFillDirection(direction);
    677         }
    678     }
    679 
    680     public void setCardRotation(float cardRotation) {
    681         mCardRotation = cardRotation;
    682         if (mRenderScript != null) {
    683             mRenderScript.setCardRotation(cardRotation);
    684         }
    685     }
    686 
    687     public void setCardsFaceTangent(boolean faceTangent) {
    688         mCardsFaceTangent = faceTangent;
    689         if (mRenderScript != null) {
    690             mRenderScript.setCardsFaceTangent(faceTangent);
    691         }
    692     }
    693 
    694     public void setSwaySensitivity(float swaySensitivity) {
    695         mSwaySensitivity = swaySensitivity;
    696         if (mRenderScript != null) {
    697             mRenderScript.setSwaySensitivity(swaySensitivity);
    698         }
    699     }
    700 
    701     public void setFrictionCoefficient(float frictionCoefficient) {
    702         mFrictionCoefficient = frictionCoefficient;
    703         if (mRenderScript != null) {
    704             mRenderScript.setFrictionCoefficient(frictionCoefficient);
    705         }
    706     }
    707 
    708     public void setDragFactor(float dragFactor) {
    709         mDragFactor = dragFactor;
    710         if (mRenderScript != null) {
    711             mRenderScript.setDragFactor(dragFactor);
    712         }
    713     }
    714 
    715     public void setLookAt(float[] eye, float[] at, float[] up) {
    716         mEye = eye;
    717         mAt = at;
    718         mUp = up;
    719         if (mRenderScript != null) {
    720             mRenderScript.setLookAt(eye, at, up);
    721         }
    722     }
    723 
    724     /**
    725      * This sets the number of cards in the distance that will be shown "rezzing in".
    726      * These alpha values will be faded in from the background to the foreground over
    727      * 'n' cards.  A floating point value is used to allow subtly changing the rezzing in
    728      * position.
    729      *
    730      * @param n the number of cards to rez in.
    731      */
    732     public void setRezInCardCount(float n) {
    733         mRezInCardCount = n;
    734         if (mRenderScript != null) {
    735             mRenderScript.setRezInCardCount(n);
    736         }
    737     }
    738 
    739     /**
    740      * This sets the duration (in ms) that a card takes to fade in when loaded via a call
    741      * to {@link CarouselView#setTextureForItem(int, Bitmap)}. The timer starts the
    742      * moment {@link CarouselView#setTextureForItem(int, Bitmap)} is called and continues
    743      * until all of the cards have faded in.  Note: using large values will extend the
    744      * animation until all cards have faded in.
    745      *
    746      * @param t The time, in milliseconds
    747      */
    748     public void setFadeInDuration(long t) {
    749         mFadeInDuration = t;
    750         if (mRenderScript != null) {
    751             mRenderScript.setFadeInDuration(t);
    752         }
    753     }
    754 
    755     /**
    756      * This sets the duration (in ms) that a card takes to fade in when it is initially created,
    757      * such as when it is added or when the application starts. The timer starts at the moment
    758      * when the card is first created. Replacing a card's contents does not affect the timer.
    759      * @param t The time, in milliseconds
    760      */
    761     public void setCardCreationFadeDuration(long t) {
    762         mCardCreationFadeDuration = t;
    763         if (mRenderScript != null) {
    764             mRenderScript.setCardCreationFadeDuration(t);
    765         }
    766     }
    767 
    768     /**
    769      * Tells the carousel that a touch event has started at the designated location.
    770      * @param x The number of pixels from the left edge that the event occurred
    771      * @param y The number of pixels from the top edge that the event occurred
    772      * @param t The time stamp of the event
    773      */
    774     public void onTouchStarted(float x, float y, long t) {
    775         mRenderScript.doStart(x, y, t);
    776     }
    777 
    778     /**
    779      * Tells the carousel that a touch event has moved to the designated location.
    780      * @param x The number of pixels from the left edge that the event occurred
    781      * @param y The number of pixels from the top edge that the event occurred
    782      * @param t The time stamp of the event
    783      */
    784     public void onTouchMoved(float x, float y, long t) {
    785         mRenderScript.doMotion(x, y, t);
    786     }
    787 
    788     /**
    789      * Tells the carousel that the user has long-pressed.
    790      */
    791     public void onLongPress() {
    792         mRenderScript.doLongPress();
    793     }
    794 
    795     /**
    796      * Tells the carousel that a touch event has stopped at the designated location.
    797      * @param x The number of pixels from the left edge that the event occurred
    798      * @param y The number of pixels from the top edge that the event occurred
    799      * @param t The time stamp of the event
    800      */
    801     public void onTouchStopped(float x, float y, long t) {
    802         mRenderScript.doStop(x, y, t);
    803     }
    804 
    805     /**
    806      * Whether to use alpha when drawing a primitive: on for translucent, off for opaque.
    807      */
    808     public static final int STORE_CONFIG_ALPHA = 1;
    809 
    810     /**
    811      * Whether to read from the depth buffer when rendering. Determines with glDepthFunc()
    812      * is given GL_LESS or GL_ALWAYS. On for GL_LESS, off for GL_ALWAYS.
    813      */
    814     public static final int STORE_CONFIG_DEPTH_READS = 2;
    815 
    816     /**
    817      * Whether to write to the depth buffer when rendering. Passed to glDepthMask().
    818      */
    819     public static final int STORE_CONFIG_DEPTH_WRITES = 4;
    820 
    821     /**
    822      * Set the StoreConfig parameters that will be used for each mesh primitive.
    823      *
    824      * Each integer in the array is a bitfield composed of
    825      * {@link CarouselController#STORE_CONFIG_ALPHA},
    826      * {@link CarouselController#STORE_CONFIG_DEPTH_READS}, and
    827      * {@link CarouselController#STORE_CONFIG_DEPTH_WRITES}.
    828      *
    829      * These parameters MUST correspond to primitives in geometry previously set in
    830      * {@link CarouselController#setDefaultGeometry(int)} or
    831      * {@link CarouselController#setLoadingGeometry(int)} or
    832      * {@link CarouselController#setGeometryForItem(int,Mesh)}.
    833      *
    834      * @param configs An array, each element of which corresponds to an ordered mesh primitive
    835      */
    836     public void setStoreConfigs(int configs[]) {
    837         mStoreConfigs = configs;
    838         if (mRenderScript != null) {
    839             mRenderScript.setStoreConfigs(configs);
    840         }
    841     }
    842 }
    843