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
17package com.android.ex.carousel;
18
19import com.android.ex.carousel.CarouselRS.CarouselCallback;
20import com.android.ex.carousel.CarouselView.DetailAlignment;
21
22import android.graphics.Bitmap;
23import android.renderscript.Float4;
24import android.renderscript.Mesh;
25import android.renderscript.RenderScriptGL;
26import 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 */
36public 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