CarouselRS.java revision e8cab95c5f73ddf6843d82793decc3adb4692860
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 android.content.res.Resources; 20import android.graphics.Bitmap; 21import android.graphics.Rect; 22import android.renderscript.*; 23import android.renderscript.RenderScript.RSMessageHandler; 24import android.util.Log; 25 26import static android.renderscript.Element.*; 27 28/** 29 * This is a support class for Carousel renderscript. It handles most of the low-level interactions 30 * with Renderscript as well as dispatching events. 31 * 32 */ 33public class CarouselRS { 34 private static final int DEFAULT_VISIBLE_SLOTS = 1; 35 private static final int DEFAULT_CARD_COUNT = 0; 36 private static final int DEFAULT_ROW_COUNT = 1; 37 38 // Client messages *** THIS LIST MUST MATCH THOSE IN carousel.rs *** 39 public static final int CMD_CARD_SELECTED = 100; 40 public static final int CMD_DETAIL_SELECTED = 105; 41 public static final int CMD_CARD_LONGPRESS = 110; 42 public static final int CMD_REQUEST_TEXTURE = 200; 43 public static final int CMD_INVALIDATE_TEXTURE = 210; 44 public static final int CMD_REQUEST_GEOMETRY = 300; 45 public static final int CMD_INVALIDATE_GEOMETRY = 310; 46 public static final int CMD_ANIMATION_STARTED = 400; 47 public static final int CMD_ANIMATION_FINISHED = 500; 48 public static final int CMD_REQUEST_DETAIL_TEXTURE = 600; 49 public static final int CMD_INVALIDATE_DETAIL_TEXTURE = 610; 50 public static final int CMD_PING = 1000; // for debugging 51 52 // Drag models *** THIS LIST MUST MATCH THOSE IN carousel.rs *** 53 public static final int DRAG_MODEL_SCREEN_DELTA = 0; 54 public static final int DRAG_MODEL_PLANE = 1; 55 public static final int DRAG_MODEL_CYLINDER_INSIDE = 2; 56 public static final int DRAG_MODEL_CYLINDER_OUTSIDE = 3; 57 58 public static final int FILL_DIRECTION_CCW = +1; 59 public static final int FILL_DIRECTION_CW = -1; 60 61 private static final String TAG = "CarouselRS"; 62 private static final int DEFAULT_SLOT_COUNT = 10; 63 private static final boolean MIPMAP = false; 64 private static final boolean DBG = false; 65 66 private RenderScriptGL mRS; 67 private Resources mRes; 68 private ScriptC_carousel mScript; 69 private ScriptField_Card mCards; 70 private ScriptField_FragmentShaderConstants_s mFSConst; 71 private ProgramStore mProgramStoreAlphaZ; 72 private ProgramStore mProgramStoreAlphaNoZ; 73 private ProgramStore mProgramStoreNoAlphaZ; 74 private ProgramStore mProgramStoreNoAlphaNoZ; 75 private ProgramFragment mSingleTextureFragmentProgram; 76 private ProgramFragment mMultiTextureFragmentProgram; 77 private ProgramVertex mVertexProgram; 78 private ProgramRaster mRasterProgram; 79 private Allocation[] mAllocationPool; 80 private int mVisibleSlots; 81 private int mRowCount; 82 private int mPrefetchCardCount; 83 private CarouselCallback mCallback; 84 private float[] mEyePoint = new float[] { 2.0f, 0.0f, 0.0f }; 85 private float[] mAtPoint = new float[] { 0.0f, 0.0f, 0.0f }; 86 private float[] mUp = new float[] { 0.0f, 1.0f, 0.0f }; 87 88 private static final String mSingleTextureShader = new String( 89 "varying vec2 varTex0;" + 90 "void main() {" + 91 "vec2 t0 = varTex0.xy;" + 92 "vec4 col = texture2D(UNI_Tex0, t0);" + 93 "gl_FragColor = col; " + 94 "}"); 95 96 private static final String mMultiTextureShader = new String( 97 "varying vec2 varTex0;" + 98 "void main() {" + 99 "vec2 t0 = varTex0.xy;" + 100 "vec4 col = texture2D(UNI_Tex0, t0);" + 101 "vec4 col2 = texture2D(UNI_Tex1, t0);" + 102 "gl_FragColor = mix(col, col2, UNI_fadeAmount);}"); 103 104 public static interface CarouselCallback { 105 /** 106 * Called when a card is selected 107 * @param n the id of the card 108 */ 109 void onCardSelected(int n); 110 111 /** 112 * Called when the detail texture for a card is tapped 113 * @param n the id of the card 114 * @param x how far the user tapped from the left edge of the card, in pixels 115 * @param y how far the user tapped from the top edge of the card, in pixels 116 */ 117 void onDetailSelected(int n, int x, int y); 118 119 /** 120 * Called when a card is long-pressed 121 * @param n the id of the card 122 * @param touchPosition position of where the user pressed, in screen coordinates 123 * @param detailCoordinates position of detail texture, in screen coordinates 124 */ 125 void onCardLongPress(int n, int touchPosition[], Rect detailCoordinates); 126 127 /** 128 * Called when texture is needed for card n. This happens when the given card becomes 129 * visible. 130 * @param n the id of the card 131 */ 132 void onRequestTexture(int n); 133 134 /** 135 * Called when a texture is no longer needed for card n. This happens when the card 136 * goes out of view. 137 * @param n the id of the card 138 */ 139 void onInvalidateTexture(int n); 140 141 /** 142 * Called when detail texture is needed for card n. This happens when the given card 143 * becomes visible. 144 * @param n the id of the card 145 */ 146 void onRequestDetailTexture(int n); 147 148 /** 149 * Called when a detail texture is no longer needed for card n. This happens when the card 150 * goes out of view. 151 * @param n the id of the card 152 */ 153 void onInvalidateDetailTexture(int n); 154 155 /** 156 * Called when geometry is needed for card n. 157 * @param n the id of the card. 158 */ 159 void onRequestGeometry(int n); 160 161 /** 162 * Called when geometry is no longer needed for card n. This happens when the card goes 163 * out of view. 164 * @param n the id of the card 165 */ 166 void onInvalidateGeometry(int n); 167 168 /** 169 * Called when card animation (e.g. a fling) has started. 170 */ 171 void onAnimationStarted(); 172 173 /** 174 * Called when card animation has stopped. 175 * @param carouselRotationAngle the angle of rotation, in radians, at which the animation 176 * stopped. 177 */ 178 void onAnimationFinished(float carouselRotationAngle); 179 }; 180 181 private RSMessageHandler mRsMessage = new RSMessageHandler() { 182 public void run() { 183 if (mCallback == null) return; 184 switch (mID) { 185 case CMD_CARD_SELECTED: 186 mCallback.onCardSelected(mData[0]); 187 break; 188 189 case CMD_DETAIL_SELECTED: 190 mCallback.onDetailSelected(mData[0], mData[1], mData[2]); 191 break; 192 193 case CMD_CARD_LONGPRESS: 194 int touchPosition[] = { mData[1], mData[2] }; 195 Rect detailCoordinates = new Rect(mData[3], mData[4], mData[5], mData[6]); 196 mCallback.onCardLongPress(mData[0], touchPosition, detailCoordinates); 197 break; 198 199 case CMD_REQUEST_TEXTURE: 200 mCallback.onRequestTexture(mData[0]); 201 break; 202 203 case CMD_INVALIDATE_TEXTURE: 204 setTexture(mData[0], null); 205 mCallback.onInvalidateTexture(mData[0]); 206 break; 207 208 case CMD_REQUEST_DETAIL_TEXTURE: 209 mCallback.onRequestDetailTexture(mData[0]); 210 break; 211 212 case CMD_INVALIDATE_DETAIL_TEXTURE: 213 setDetailTexture(mData[0], 0.0f, 0.0f, 0.0f, 0.0f, null); 214 mCallback.onInvalidateDetailTexture(mData[0]); 215 break; 216 217 case CMD_REQUEST_GEOMETRY: 218 mCallback.onRequestGeometry(mData[0]); 219 break; 220 221 case CMD_INVALIDATE_GEOMETRY: 222 setGeometry(mData[0], null); 223 mCallback.onInvalidateGeometry(mData[0]); 224 break; 225 226 case CMD_ANIMATION_STARTED: 227 mCallback.onAnimationStarted(); 228 break; 229 230 case CMD_ANIMATION_FINISHED: 231 mCallback.onAnimationFinished(Float.intBitsToFloat(mData[0])); 232 break; 233 234 case CMD_PING: 235 if (DBG) Log.v(TAG, "PING..."); 236 break; 237 238 default: 239 Log.e(TAG, "Unknown RSMessage: " + mID); 240 } 241 } 242 }; 243 244 public CarouselRS(RenderScriptGL rs, Resources res, int resId) { 245 mRS = rs; 246 mRes = res; 247 248 // create the script object 249 mScript = new ScriptC_carousel(mRS, mRes, resId); 250 mRS.setMessageHandler(mRsMessage); 251 initProgramStore(); 252 initFragmentProgram(); 253 initRasterProgram(); 254 initVertexProgram(); 255 setSlotCount(DEFAULT_SLOT_COUNT); 256 setVisibleSlots(DEFAULT_VISIBLE_SLOTS); 257 setRowCount(DEFAULT_ROW_COUNT); 258 createCards(DEFAULT_CARD_COUNT); 259 setStartAngle(0.0f); 260 setCarouselRotationAngle(0.0f); 261 setRadius(1.0f); 262 setLookAt(mEyePoint, mAtPoint, mUp); 263 setRadius(20.0f); 264 // Fov: 25 265 } 266 267 public void setLookAt(float[] eye, float[] at, float[] up) { 268 for (int i = 0; i < 3; i++) { 269 mEyePoint[i] = eye[i]; 270 mAtPoint[i] = at[i]; 271 mUp[i] = up[i]; 272 } 273 mScript.invoke_lookAt(eye[0], eye[1], eye[2], at[0], at[1], at[2], up[0], up[1], up[2]); 274 } 275 276 public void setRadius(float radius) { 277 mScript.invoke_setRadius(radius); 278 } 279 280 public void setCardRotation(float cardRotation) { 281 mScript.set_cardRotation(cardRotation); 282 } 283 284 public void setCardsFaceTangent(boolean faceTangent) { 285 mScript.set_cardsFaceTangent(faceTangent); 286 } 287 288 public void setSwaySensitivity(float swaySensitivity) { 289 mScript.set_swaySensitivity(swaySensitivity); 290 } 291 292 public void setFrictionCoefficient(float frictionCoeff) { 293 mScript.set_frictionCoeff(frictionCoeff); 294 } 295 296 public void setDragFactor(float dragFactor) { 297 mScript.set_dragFactor(dragFactor); 298 } 299 300 public void setDragModel(int model) { 301 mScript.set_dragModel(model); 302 } 303 304 public void setFillDirection(int direction) { 305 mScript.set_fillDirection(direction); 306 } 307 308 public void setDefaultCardMatrix(float[] matrix) { 309 int dimensions; 310 if (matrix == null || matrix.length == 0) { 311 dimensions = 0; 312 } else if (matrix.length == 16) { 313 dimensions = 4; 314 } else if (matrix.length == 9) { 315 dimensions = 3; 316 } else { 317 throw new IllegalArgumentException("matrix length not 0,9 or 16"); 318 } 319 320 Matrix4f rsMatrix = new Matrix4f(); // initialized as identity. 321 for (int i = 0; i < dimensions; i++) { 322 for (int j = 0; j < dimensions; j++) { 323 rsMatrix.set(i, j, matrix[i*dimensions + j]); 324 } 325 } 326 mScript.set_defaultCardMatrix(rsMatrix); 327 } 328 329 private void initVertexProgram() { 330 ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS, null, null); 331 mVertexProgram = pvb.create(); 332 ProgramVertex.MatrixAllocation pva = new ProgramVertex.MatrixAllocation(mRS); 333 mVertexProgram.bindAllocation(pva); 334 pva.setupProjectionNormalized(1, 1); 335 mScript.set_vertexProgram(mVertexProgram); 336 } 337 338 private void initRasterProgram() { 339 ProgramRaster.Builder programRasterBuilder = new ProgramRaster.Builder(mRS); 340 mRasterProgram = programRasterBuilder.create(); 341 //mRasterProgram.setCullMode(CullMode.NONE); 342 mScript.set_rasterProgram(mRasterProgram); 343 } 344 345 private void initFragmentProgram() { 346 // 347 // Single texture program 348 // 349 ProgramFragment.ShaderBuilder pfbSingle = new ProgramFragment.ShaderBuilder(mRS); 350 // Specify the resource that contains the shader string 351 pfbSingle.setShader(mSingleTextureShader); 352 // Tell the builder how many textures we have 353 pfbSingle.setTextureCount(1); 354 mSingleTextureFragmentProgram = pfbSingle.create(); 355 // Bind the source of constant data 356 mSingleTextureFragmentProgram.bindSampler(Sampler.CLAMP_LINEAR(mRS), 0); 357 358 // 359 // Multi texture program 360 // 361 mFSConst = new ScriptField_FragmentShaderConstants_s(mRS, 1); 362 mScript.bind_shaderConstants(mFSConst); 363 ProgramFragment.ShaderBuilder pfbMulti = new ProgramFragment.ShaderBuilder(mRS); 364 // Specify the resource that contains the shader string 365 pfbMulti.setShader(mMultiTextureShader); 366 // Tell the builder how many textures we have 367 pfbMulti.setTextureCount(2); 368 // Define the constant input layout 369 pfbMulti.addConstant(mFSConst.getAllocation().getType()); 370 mMultiTextureFragmentProgram = pfbMulti.create(); 371 // Bind the source of constant data 372 mMultiTextureFragmentProgram.bindConstants(mFSConst.getAllocation(), 0); 373 mMultiTextureFragmentProgram.bindSampler(Sampler.CLAMP_LINEAR(mRS), 0); 374 mMultiTextureFragmentProgram.bindSampler(Sampler.CLAMP_LINEAR(mRS), 1); 375 376 mScript.set_linearClamp(Sampler.CLAMP_LINEAR(mRS)); 377 mScript.set_singleTextureFragmentProgram(mSingleTextureFragmentProgram); 378 mScript.set_multiTextureFragmentProgram(mMultiTextureFragmentProgram); 379 } 380 381 private void initProgramStore() { 382 final boolean dither = true; 383 mProgramStoreAlphaZ = new ProgramStore.Builder(mRS) 384 .setBlendFunc(ProgramStore.BlendSrcFunc.ONE, 385 ProgramStore.BlendDstFunc.ONE_MINUS_SRC_ALPHA) 386 .setDitherEnable(dither) 387 .setDepthFunc(ProgramStore.DepthFunc.LESS) 388 .setDepthMask(true) 389 .create(); 390 mScript.set_programStoreAlphaZ(mProgramStoreAlphaZ); 391 392 mProgramStoreAlphaNoZ = new ProgramStore.Builder(mRS) 393 .setBlendFunc(ProgramStore.BlendSrcFunc.ONE, 394 ProgramStore.BlendDstFunc.ONE_MINUS_SRC_ALPHA) 395 .setDitherEnable(dither) 396 .setDepthFunc(ProgramStore.DepthFunc.ALWAYS) 397 .setDepthMask(false) 398 .create(); 399 mScript.set_programStoreAlphaNoZ(mProgramStoreAlphaNoZ); 400 401 mProgramStoreNoAlphaZ = new ProgramStore.Builder(mRS) 402 .setBlendFunc(ProgramStore.BlendSrcFunc.ONE, ProgramStore.BlendDstFunc.ZERO) 403 .setDitherEnable(dither) 404 .setDepthFunc(ProgramStore.DepthFunc.LESS) 405 .setDepthMask(true) 406 .create(); 407 mScript.set_programStoreNoAlphaZ(mProgramStoreNoAlphaZ); 408 409 mProgramStoreNoAlphaNoZ = new ProgramStore.Builder(mRS) 410 .setBlendFunc(ProgramStore.BlendSrcFunc.ONE, ProgramStore.BlendDstFunc.ZERO) 411 .setDitherEnable(dither) 412 .setDepthFunc(ProgramStore.DepthFunc.ALWAYS) 413 .setDepthMask(false) 414 .create(); 415 mScript.set_programStoreNoAlphaNoZ(mProgramStoreNoAlphaNoZ); 416 } 417 418 public void createCards(int count) 419 { 420 // Because RenderScript can't have allocations with 0 dimensions, we always create 421 // an allocation of at least one card. This relies on invoke_createCards() to keep 422 // track of when the allocation is not valid. 423 if (mCards != null) { 424 // resize the array 425 int oldSize = mCards.getAllocation().getType().getX(); 426 int newSize = count > 0 ? count : 1; 427 mCards.resize(newSize); 428 mScript.invoke_createCards(oldSize, count); 429 } else { 430 // create array from scratch 431 mCards = new ScriptField_Card(mRS, count > 0 ? count : 1); 432 mScript.bind_cards(mCards); 433 mScript.invoke_createCards(0, count); 434 } 435 } 436 437 public void setVisibleSlots(int count) 438 { 439 mVisibleSlots = count; 440 mScript.set_visibleSlotCount(count); 441 } 442 443 public void setVisibleDetails(int count) { 444 mScript.set_visibleDetailCount(count); 445 } 446 447 public void setRowCount(int count) { 448 mRowCount = count; 449 mScript.set_rowCount(count); 450 } 451 452 public void setRowSpacing(float spacing) { 453 mScript.set_rowSpacing(spacing); 454 } 455 456 public void setPrefetchCardCount(int count) { 457 mPrefetchCardCount = count; 458 mScript.set_prefetchCardCount(count); 459 } 460 461 public void setDetailTextureAlignment(int alignment) { 462 mScript.set_detailTextureAlignment(alignment); 463 } 464 465 public void setForceBlendCardsWithZ(boolean enabled) { 466 mScript.set_forceBlendCardsWithZ(enabled); 467 } 468 469 public void setDrawRuler(boolean drawRuler) { 470 mScript.set_drawRuler(drawRuler); 471 } 472 473 public void setDefaultBitmap(Bitmap bitmap) 474 { 475 mScript.set_defaultTexture(allocationFromBitmap(bitmap, MIPMAP)); 476 } 477 478 public void setLoadingBitmap(Bitmap bitmap) 479 { 480 mScript.set_loadingTexture(allocationFromBitmap(bitmap, MIPMAP)); 481 } 482 483 public void setDefaultGeometry(Mesh mesh) 484 { 485 mScript.set_defaultGeometry(mesh); 486 } 487 488 public void setLoadingGeometry(Mesh mesh) 489 { 490 mScript.set_loadingGeometry(mesh); 491 } 492 493 public void setStartAngle(float theta) 494 { 495 mScript.set_startAngle(theta); 496 } 497 498 public void setCarouselRotationAngle(float theta) { 499 mScript.invoke_setCarouselRotationAngle(theta); 500 } 501 502 public void setCallback(CarouselCallback callback) 503 { 504 mCallback = callback; 505 } 506 507 private Allocation allocationFromBitmap(Bitmap bitmap, boolean mipmap) 508 { 509 if (bitmap == null) return null; 510 Allocation allocation = Allocation.createFromBitmap(mRS, bitmap, 511 elementForBitmap(bitmap, Bitmap.Config.ARGB_4444), mipmap); 512 allocation.uploadToTexture(0); 513 return allocation; 514 } 515 516 private Allocation allocationFromPool(int n, Bitmap bitmap, boolean mipmap) 517 { 518 int count = (mVisibleSlots + mPrefetchCardCount) * mRowCount; 519 if (mAllocationPool == null || mAllocationPool.length != count) { 520 Allocation[] tmp = new Allocation[count]; 521 int oldsize = mAllocationPool == null ? 0 : mAllocationPool.length; 522 for (int i = 0; i < Math.min(count, oldsize); i++) { 523 tmp[i] = mAllocationPool[i]; 524 } 525 mAllocationPool = tmp; 526 } 527 Allocation allocation = mAllocationPool[n % count]; 528 if (allocation == null) { 529 allocation = allocationFromBitmap(bitmap, mipmap); 530 mAllocationPool[n % count] = allocation; 531 } else if (bitmap != null) { 532 if (bitmap.getWidth() == allocation.getType().getX() 533 && bitmap.getHeight() == allocation.getType().getY()) { 534 allocation.copyFrom(bitmap); 535 allocation.uploadToTexture(0); 536 } else { 537 Log.v(TAG, "Warning, bitmap has different size. Taking slow path"); 538 allocation = allocationFromBitmap(bitmap, mipmap); 539 mAllocationPool[n % count] = allocation; 540 } 541 } 542 return allocation; 543 } 544 545 public void setTexture(int n, Bitmap bitmap) 546 { 547 if (n < 0) throw new IllegalArgumentException("Index cannot be negative"); 548 549 synchronized(this) { 550 ScriptField_Card.Item item = mCards.get(n); 551 if (item == null) { 552 if (DBG) Log.v(TAG, "setTexture(): no item at index " + n); 553 item = new ScriptField_Card.Item(); 554 } 555 if (bitmap != null) { 556 item.texture = allocationFromPool(n, bitmap, MIPMAP); 557 } else { 558 if (item.texture != null) { 559 if (DBG) Log.v(TAG, "unloading texture " + n); 560 item.texture = null; 561 } 562 } 563 mCards.set(item, n, false); // This is primarily used for reference counting. 564 mScript.invoke_setTexture(n, item.texture); 565 } 566 } 567 568 void setDetailTexture(int n, float offx, float offy, float loffx, float loffy, Bitmap bitmap) 569 { 570 if (n < 0) throw new IllegalArgumentException("Index cannot be negative"); 571 572 synchronized(this) { 573 ScriptField_Card.Item item = mCards.get(n); 574 if (item == null) { 575 if (DBG) Log.v(TAG, "setDetailTexture(): no item at index " + n); 576 item = new ScriptField_Card.Item(); 577 } 578 float width = 0.0f; 579 float height = 0.0f; 580 if (bitmap != null) { 581 item.detailTexture = allocationFromBitmap(bitmap, MIPMAP); 582 width = bitmap.getWidth(); 583 height = bitmap.getHeight(); 584 } else { 585 if (item.detailTexture != null) { 586 if (DBG) Log.v(TAG, "unloading detail texture " + n); 587 // Don't wait for GC to free native memory. 588 // Only works if textures are not shared. 589 item.detailTexture.destroy(); 590 item.detailTexture = null; 591 } 592 } 593 mCards.set(item, n, false); // This is primarily used for reference counting. 594 mScript.invoke_setDetailTexture(n, offx, offy, loffx, loffy, item.detailTexture); 595 } 596 } 597 598 void invalidateTexture(int n, boolean eraseCurrent) 599 { 600 if (n < 0) throw new IllegalArgumentException("Index cannot be negative"); 601 602 synchronized(this) { 603 ScriptField_Card.Item item = mCards.get(n); 604 if (item == null) { 605 // This card was never created, so there's nothing to invalidate. 606 return; 607 } 608 if (eraseCurrent && item.texture != null) { 609 if (DBG) Log.v(TAG, "unloading texture " + n); 610 // Don't wait for GC to free native memory. 611 // Only works if textures are not shared. 612 item.texture.destroy(); 613 item.texture = null; 614 } 615 mCards.set(item, n, false); // This is primarily used for reference counting. 616 mScript.invoke_invalidateTexture(n, eraseCurrent); 617 } 618 } 619 620 void invalidateDetailTexture(int n, boolean eraseCurrent) 621 { 622 if (n < 0) throw new IllegalArgumentException("Index cannot be negative"); 623 624 synchronized(this) { 625 ScriptField_Card.Item item = mCards.get(n); 626 if (item == null) { 627 // This card was never created, so there's nothing to invalidate. 628 return; 629 } 630 if (eraseCurrent && item.detailTexture != null) { 631 if (DBG) Log.v(TAG, "unloading detail texture " + n); 632 // Don't wait for GC to free native memory. 633 // Only works if textures are not shared. 634 item.detailTexture.destroy(); 635 item.detailTexture = null; 636 } 637 mCards.set(item, n, false); // This is primarily used for reference counting. 638 mScript.invoke_invalidateDetailTexture(n, eraseCurrent); 639 } 640 } 641 642 public void setGeometry(int n, Mesh geometry) 643 { 644 if (n < 0) throw new IllegalArgumentException("Index cannot be negative"); 645 646 synchronized(this) { 647 final boolean mipmap = false; 648 ScriptField_Card.Item item = mCards.get(n); 649 if (item == null) { 650 if (DBG) Log.v(TAG, "setGeometry(): no item at index " + n); 651 item = new ScriptField_Card.Item(); 652 } 653 if (geometry != null) { 654 item.geometry = geometry; 655 } else { 656 if (DBG) Log.v(TAG, "unloading geometry " + n); 657 if (item.geometry != null) { 658 // item.geometry.destroy(); 659 item.geometry = null; 660 } 661 } 662 mCards.set(item, n, false); 663 mScript.invoke_setGeometry(n, item.geometry); 664 } 665 } 666 667 public void setBackgroundColor(Float4 color) { 668 mScript.set_backgroundColor(color); 669 } 670 671 public void setBackgroundTexture(Bitmap bitmap) { 672 Allocation texture = null; 673 if (bitmap != null) { 674 texture = Allocation.createFromBitmap(mRS, bitmap, 675 elementForBitmap(bitmap, Bitmap.Config.RGB_565), MIPMAP); 676 texture.uploadToTexture(0); 677 } 678 mScript.set_backgroundTexture(texture); 679 } 680 681 public void setDetailLineTexture(Bitmap bitmap) { 682 Allocation texture = null; 683 if (bitmap != null) { 684 texture = Allocation.createFromBitmap(mRS, bitmap, 685 elementForBitmap(bitmap, Bitmap.Config.ARGB_4444), MIPMAP); 686 texture.uploadToTexture(0); 687 } 688 mScript.set_detailLineTexture(texture); 689 } 690 691 public void setDetailLoadingTexture(Bitmap bitmap) { 692 Allocation texture = null; 693 if (bitmap != null) { 694 texture = Allocation.createFromBitmap(mRS, bitmap, 695 elementForBitmap(bitmap, Bitmap.Config.ARGB_4444), MIPMAP); 696 texture.uploadToTexture(0); 697 } 698 mScript.set_detailLoadingTexture(texture); 699 } 700 701 public void pauseRendering() { 702 // Used to update multiple states at once w/o redrawing for each. 703 mRS.bindRootScript(null); 704 } 705 706 public void resumeRendering() { 707 mRS.bindRootScript(mScript); 708 } 709 710 public void doLongPress() { 711 mScript.invoke_doLongPress(); 712 } 713 714 public void doMotion(float x, float y, long t) { 715 mScript.invoke_doMotion(x, y, t); 716 } 717 718 public void doStart(float x, float y, long t) { 719 mScript.invoke_doStart(x, y, t); 720 } 721 722 public void doStop(float x, float y, long t) { 723 mScript.invoke_doStop(x, y, t); 724 } 725 726 public void setSlotCount(int n) { 727 mScript.set_slotCount(n); 728 } 729 730 public void setRezInCardCount(float alpha) { 731 mScript.set_rezInCardCount(alpha); 732 } 733 734 public void setFadeInDuration(long t) { 735 mScript.set_fadeInDuration((int)t); // TODO: Remove cast when RS supports exporting longs 736 } 737 738 private Element elementForBitmap(Bitmap bitmap, Bitmap.Config defaultConfig) { 739 Bitmap.Config config = bitmap.getConfig(); 740 if (config == null) { 741 config = defaultConfig; 742 } 743 if (config == Bitmap.Config.ALPHA_8) { 744 return A_8(mRS); 745 } else if (config == Bitmap.Config.RGB_565) { 746 return RGB_565(mRS); 747 } else if (config == Bitmap.Config.ARGB_4444) { 748 return RGBA_4444(mRS); 749 } else if (config == Bitmap.Config.ARGB_8888) { 750 return RGBA_8888(mRS); 751 } else { 752 throw new IllegalArgumentException("Unknown configuration"); 753 } 754 } 755} 756