CarouselView.java revision c0bb8af58ae15674178f2db240283719918c6f28
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; 20 21import android.content.Context; 22import android.content.res.Resources; 23import android.content.res.TypedArray; 24import android.graphics.Bitmap; 25import android.graphics.Rect; 26import android.graphics.Bitmap.Config; 27import android.renderscript.FileA3D; 28import android.renderscript.Mesh; 29import android.renderscript.RSSurfaceView; 30import android.renderscript.RenderScriptGL; 31import android.util.AttributeSet; 32import android.util.Log; 33import android.view.MotionEvent; 34import android.view.SurfaceHolder; 35 36public abstract class CarouselView extends RSSurfaceView { 37 private static final boolean USE_DEPTH_BUFFER = true; 38 private final int DEFAULT_SLOT_COUNT = 10; 39 private final Bitmap DEFAULT_BITMAP = Bitmap.createBitmap(1, 1, Config.RGB_565); 40 private final float DEFAULT_RADIUS = 20.0f; 41 private final float DEFAULT_SWAY_SENSITIVITY = 0.0f; 42 private final float DEFAULT_FRICTION_COEFFICIENT = 10.0f; 43 private final float DEFAULT_DRAG_FACTOR = 0.25f; 44 private static final String TAG = "CarouselView"; 45 private CarouselRS mRenderScript; 46 private RenderScriptGL mRS; 47 private Context mContext; 48 private boolean mTracking; 49 50 // These are meant to shadow the state of the renderer in case the surface changes. 51 private Bitmap mDefaultBitmap; 52 private Bitmap mLoadingBitmap; 53 private Bitmap mBackgroundBitmap; 54 private Mesh mDefaultGeometry; 55 private Mesh mLoadingGeometry; 56 private int mCardCount = 0; 57 private int mVisibleSlots = 0; 58 private float mStartAngle; 59 private float mRadius = DEFAULT_RADIUS; 60 private float mCardRotation = 0.0f; 61 private float mSwaySensitivity = DEFAULT_SWAY_SENSITIVITY; 62 private float mFrictionCoefficient = DEFAULT_FRICTION_COEFFICIENT; 63 private float mDragFactor = DEFAULT_DRAG_FACTOR; 64 private int mSlotCount = DEFAULT_SLOT_COUNT; 65 private float mEye[] = { 20.6829f, 2.77081f, 16.7314f }; 66 private float mAt[] = { 14.7255f, -3.40001f, -1.30184f }; 67 private float mUp[] = { 0.0f, 1.0f, 0.0f }; 68 69 public static class Info { 70 public Info(int _resId) { resId = _resId; } 71 public int resId; // resource for renderscript resource (e.g. R.raw.carousel) 72 } 73 74 public abstract Info getRenderScriptInfo(); 75 76 public CarouselView(Context context) { 77 this(context, null); 78 } 79 80 /** 81 * Constructor used when this widget is created from a layout file. 82 */ 83 public CarouselView(Context context, AttributeSet attrs) { 84 super(context, attrs); 85 mContext = context; 86 boolean useDepthBuffer = true; 87 ensureRenderScript(); 88 // TODO: add parameters to layout 89 } 90 91 private void ensureRenderScript() { 92 mRS = createRenderScript(USE_DEPTH_BUFFER); 93 mRenderScript = new CarouselRS(); 94 mRenderScript.init(mRS, getResources(), getRenderScriptInfo().resId); 95 } 96 97 @Override 98 public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 99 super.surfaceChanged(holder, format, w, h); 100 //mRS.contextSetSurface(w, h, holder.getSurface()); 101 mRenderScript.init(mRS, getResources(), getRenderScriptInfo().resId); 102 setSlotCount(mSlotCount); 103 createCards(mCardCount); 104 setVisibleSlots(mVisibleSlots); 105 setCallback(mCarouselCallback); 106 setDefaultBitmap(mDefaultBitmap); 107 setLoadingBitmap(mLoadingBitmap); 108 setDefaultGeometry(mDefaultGeometry); 109 setLoadingGeometry(mLoadingGeometry); 110 setBackgroundBitmap(mBackgroundBitmap); 111 setStartAngle(mStartAngle); 112 setRadius(mRadius); 113 setCardRotation(mCardRotation); 114 setSwaySensitivity(mSwaySensitivity); 115 setFrictionCoefficient(mFrictionCoefficient); 116 setDragFactor(mDragFactor); 117 setLookAt(mEye, mAt, mUp); 118 } 119 120 /** 121 * Loads geometry from a resource id. 122 * 123 * @param resId 124 * @return the loaded mesh or null if it cannot be loaded 125 */ 126 public Mesh loadGeometry(int resId) { 127 Resources res = mContext.getResources(); 128 FileA3D model = FileA3D.createFromResource(mRS, res, resId); 129 FileA3D.IndexEntry entry = model.getIndexEntry(0); 130 if(entry == null || entry.getClassID() != FileA3D.ClassID.MESH) { 131 return null; 132 } 133 return (Mesh) entry.getObject(); 134 } 135 136 /** 137 * Load A3D file from resource. If resId == 0, will clear geometry for this item. 138 * @param n 139 * @param resId 140 */ 141 public void setGeometryForItem(int n, Mesh mesh) { 142 if (mRenderScript != null) { 143 mRenderScript.setGeometry(n, mesh); 144 } 145 } 146 147 public void setSlotCount(int n) { 148 mSlotCount = n; 149 if (mRenderScript != null) { 150 mRenderScript.setSlotCount(n); 151 } 152 } 153 154 public void setVisibleSlots(int n) { 155 mVisibleSlots = n; 156 if (mRenderScript != null) { 157 mRenderScript.setVisibleSlots(n); 158 } 159 } 160 161 public void createCards(int n) { 162 mCardCount = n; 163 if (mRenderScript != null) { 164 mRenderScript.createCards(n); 165 } 166 } 167 168 public void setTextureForItem(int n, Bitmap bitmap) { 169 // Also check against mRS, to handle the case where the result is being delivered by a 170 // background thread but the sender no longer exists. 171 if (mRenderScript != null && mRS != null) { 172 Log.v(TAG, "setTextureForItem(" + n + ")"); 173 mRenderScript.setTexture(n, bitmap); 174 Log.v(TAG, "done"); 175 } 176 } 177 178 public void setDefaultBitmap(Bitmap bitmap) { 179 mDefaultBitmap = bitmap; 180 if (mRenderScript != null) { 181 mRenderScript.setDefaultBitmap(bitmap); 182 } 183 } 184 185 public void setLoadingBitmap(Bitmap bitmap) { 186 mLoadingBitmap = bitmap; 187 if (mRenderScript != null) { 188 mRenderScript.setLoadingBitmap(bitmap); 189 } 190 } 191 192 public void setBackgroundBitmap(Bitmap bitmap) { 193 mBackgroundBitmap = bitmap; 194 if (mRenderScript != null) { 195 mRenderScript.setBackgroundTexture(bitmap); 196 } 197 } 198 199 public void setDefaultGeometry(Mesh mesh) { 200 mDefaultGeometry = mesh; 201 if (mRenderScript != null) { 202 mRenderScript.setDefaultGeometry(mesh); 203 } 204 } 205 206 public void setLoadingGeometry(Mesh mesh) { 207 mLoadingGeometry = mesh; 208 if (mRenderScript != null) { 209 mRenderScript.setLoadingGeometry(mesh); 210 } 211 } 212 213 public void setCallback(CarouselCallback callback) 214 { 215 mCarouselCallback = callback; 216 if (mRenderScript != null) { 217 mRenderScript.setCallback(callback); 218 } 219 } 220 221 public void setStartAngle(float angle) 222 { 223 mStartAngle = angle; 224 if (mRenderScript != null) { 225 mRenderScript.setStartAngle(angle); 226 } 227 } 228 229 public void setRadius(float radius) { 230 mRadius = radius; 231 if (mRenderScript != null) { 232 mRenderScript.setRadius(radius); 233 } 234 } 235 236 public void setCardRotation(float cardRotation) { 237 mCardRotation = cardRotation; 238 if (mRenderScript != null) { 239 mRenderScript.setCardRotation(cardRotation); 240 } 241 } 242 243 public void setSwaySensitivity(float swaySensitivity) { 244 mSwaySensitivity = swaySensitivity; 245 if (mRenderScript != null) { 246 mRenderScript.setSwaySensitivity(swaySensitivity); 247 } 248 } 249 250 public void setFrictionCoefficient(float frictionCoefficient) { 251 mFrictionCoefficient = frictionCoefficient; 252 if (mRenderScript != null) { 253 mRenderScript.setFrictionCoefficient(frictionCoefficient); 254 } 255 } 256 257 public void setDragFactor(float dragFactor) { 258 mDragFactor = dragFactor; 259 if (mRenderScript != null) { 260 mRenderScript.setDragFactor(dragFactor); 261 } 262 } 263 264 public void setLookAt(float[] eye, float[] at, float[] up) { 265 mEye = eye; 266 mAt = at; 267 mUp = up; 268 if (mRenderScript != null) { 269 mRenderScript.setLookAt(eye, at, up); 270 } 271 } 272 273 @Override 274 protected void onDetachedFromWindow() { 275 super.onDetachedFromWindow(); 276 if(mRS != null) { 277 mRS = null; 278 destroyRenderScript(); 279 } 280 } 281 282 @Override 283 protected void onAttachedToWindow() { 284 super.onAttachedToWindow(); 285 ensureRenderScript(); 286 } 287 288 @Override 289 public boolean onTouchEvent(MotionEvent event) { 290 final int action = event.getAction(); 291 final float x = event.getX(); 292 final float y = event.getY(); 293 294 if (mRenderScript == null) { 295 return true; 296 } 297 298 switch (action) { 299 case MotionEvent.ACTION_DOWN: 300 mTracking = true; 301 mRenderScript.doStart(x, y); 302 break; 303 304 case MotionEvent.ACTION_MOVE: 305 if (mTracking) { 306 mRenderScript.doMotion(x, y); 307 } 308 break; 309 310 case MotionEvent.ACTION_UP: 311 mRenderScript.doStop(x, y); 312 mTracking = false; 313 break; 314 } 315 316 return true; 317 } 318 319 private final CarouselCallback DEBUG_CALLBACK = new CarouselCallback() { 320 public void onAnimationStarted() { 321 Log.v(TAG, "onAnimationStarted()"); 322 } 323 324 public void onAnimationFinished() { 325 Log.v(TAG, "onAnimationFinished()"); 326 } 327 328 public void onCardSelected(int n) { 329 Log.v(TAG, "onCardSelected(" + n + ")"); 330 } 331 332 public void onRequestGeometry(int n) { 333 Log.v(TAG, "onRequestGeometry(" + n + ")"); 334 } 335 336 public void onInvalidateGeometry(int n) { 337 Log.v(TAG, "onInvalidateGeometry(" + n + ")"); 338 } 339 340 public void onRequestTexture(final int n) { 341 Log.v(TAG, "onRequestTexture(" + n + ")"); 342 } 343 344 public void onInvalidateTexture(int n) { 345 Log.v(TAG, "onInvalidateTexture(" + n + ")"); 346 } 347 348 }; 349 350 private CarouselCallback mCarouselCallback = DEBUG_CALLBACK; 351} 352