package com.cooliris.media; import java.util.Random; import android.content.Context; import com.cooliris.media.FloatUtils; /** * A simple structure for a MediaItem that can be rendered. */ public final class DisplayItem { private static final float STACK_SPACING = 0.2f; private DirectLinkedList.Entry<DisplayItem> mAnimatablesEntry = new DirectLinkedList.Entry<DisplayItem>(this); private static final Random random = new Random(); private Vector3f mStacktopPosition = new Vector3f(-1.0f, -1.0f, -1.0f); private Vector3f mJitteredPosition = new Vector3f(); private boolean mHasFocus; private Vector3f mTargetPosition = new Vector3f(); private float mTargetTheta; private float mImageTheta; private int mStackId; private MediaItemTexture mThumbnailImage = null; private Texture mScreennailImage = null; private UriTexture mHiResImage = null; private float mConvergenceSpeed = 1.0f; public final MediaItem mItemRef; public float mAnimatedTheta; public float mAnimatedImageTheta; public float mAnimatedPlaceholderFade = 0f; public boolean mAlive; public Vector3f mAnimatedPosition = new Vector3f(); public DisplayItem(MediaItem item) { mItemRef = item; mAnimatedImageTheta = item.mRotation; mImageTheta = item.mRotation; if (item == null) throw new UnsupportedOperationException("Cannot create a displayitem from a null MediaItem."); } public DirectLinkedList.Entry<DisplayItem> getAnimatablesEntry() { return mAnimatablesEntry; } public final void rotateImageBy(float theta) { mImageTheta += theta; } public final void set(Vector3f position, int stackIndex, boolean performTransition) { mConvergenceSpeed = 1.0f; Vector3f animatedPosition = mAnimatedPosition; Vector3f targetPosition = mTargetPosition; int seed = stackIndex; int randomSeed = stackIndex; if (seed > 3) { seed = 3; randomSeed = 0; } if (!mAlive) { animatedPosition.set(position); animatedPosition.z = -3.0f + stackIndex * STACK_SPACING; } targetPosition.set(position); if (mStackId != stackIndex && stackIndex >= 0) { mStackId = stackIndex; } if (randomSeed == 0) { mTargetTheta = 0.0f; mTargetPosition.z = seed * STACK_SPACING; mJitteredPosition.set(0, 0, seed * STACK_SPACING); } else { int sign = (seed % 2 == 0) ? 1 : -1; if (seed != 0 && !mStacktopPosition.equals(position) && mTargetTheta == 0) { mTargetTheta = 30.0f * (0.5f - (float) Math.random()); mJitteredPosition.x = sign * 12.0f * seed + (0.5f - random.nextFloat()) * 4 * seed; mJitteredPosition.y = sign * 4 + ((sign == 1) ? -8.0f : sign * (random.nextFloat()) * 16.0f); mJitteredPosition.x *= Gallery.PIXEL_DENSITY; mJitteredPosition.y *= Gallery.PIXEL_DENSITY; mJitteredPosition.z = seed * STACK_SPACING; } } mTargetPosition.add(mJitteredPosition); mStacktopPosition.set(position); } public int getStackIndex() { return mStackId; } public Texture getThumbnailImage(Context context, MediaItemTexture.Config config) { MediaItemTexture texture = mThumbnailImage; if (texture == null && config != null) { if (mItemRef.mId != Shared.INVALID) { texture = new MediaItemTexture(context, config, mItemRef); } mThumbnailImage = texture; } return texture; } public Texture getScreennailImage(Context context) { Texture texture = mScreennailImage; if (texture == null || texture.mState == Texture.STATE_ERROR) { MediaSet parentMediaSet = mItemRef.mParentMediaSet; if (parentMediaSet != null && parentMediaSet.mDataSource.getThumbnailCache() == LocalDataSource.sThumbnailCache) { if (mItemRef.mId != Shared.INVALID && mItemRef.mId != 0) { texture = new MediaItemTexture(context, null, mItemRef); } else if (mItemRef.mContentUri != null) { texture = new UriTexture(mItemRef.mContentUri); } } else { texture = new UriTexture(mItemRef.mScreennailUri); ((UriTexture) texture).setCacheId(Utils.Crc64Long(mItemRef.mFilePath)); } mScreennailImage = texture; } return texture; } public void clearScreennailImage() { if (mScreennailImage != null) { mScreennailImage = null; mHiResImage = null; } } public void clearHiResImage() { mHiResImage = null; } public void clearThumbnail() { mThumbnailImage = null; } /** * Use this function to query the animation state of the display item * * @return true if the display item is animating */ public boolean isAnimating() { return mAlive && (!mAnimatedPosition.equals(mTargetPosition) || mAnimatedTheta != mTargetTheta || mAnimatedImageTheta != mImageTheta || mAnimatedPlaceholderFade != 1f); } /** * This function should be called every time the frame needs to be updated. */ public final void update(float timeElapsedInSec) { if (mAlive) { timeElapsedInSec *= 1.25f; Vector3f animatedPosition = mAnimatedPosition; Vector3f targetPosition = mTargetPosition; timeElapsedInSec *= mConvergenceSpeed; animatedPosition.x = FloatUtils.animate(animatedPosition.x, targetPosition.x, timeElapsedInSec); animatedPosition.y = FloatUtils.animate(animatedPosition.y, targetPosition.y, timeElapsedInSec); mAnimatedTheta = FloatUtils.animate(mAnimatedTheta, mTargetTheta, timeElapsedInSec); mAnimatedImageTheta = FloatUtils.animate(mAnimatedImageTheta, mImageTheta, timeElapsedInSec); mAnimatedPlaceholderFade = FloatUtils.animate(mAnimatedPlaceholderFade, 1f, timeElapsedInSec); animatedPosition.z = FloatUtils.animate(animatedPosition.z, targetPosition.z, timeElapsedInSec); } } /** * Commits all animations for the Display Item */ public final void commit() { mAnimatedPosition.set(mTargetPosition); mAnimatedTheta = mTargetTheta; mAnimatedImageTheta = mImageTheta; } public final void setHasFocus(boolean hasFocus, boolean pushDown) { mConvergenceSpeed = 2.0f; mHasFocus = hasFocus; int seed = mStackId; if (seed > 3) { seed = 3; } if (hasFocus) { mTargetPosition.set(mStacktopPosition); mTargetPosition.add(mJitteredPosition); mTargetPosition.add(mJitteredPosition); mTargetPosition.z = seed * STACK_SPACING + (pushDown ? 1.0f : -0.5f); } else { mTargetPosition.set(mStacktopPosition); mTargetPosition.add(mJitteredPosition); mTargetPosition.z = seed * STACK_SPACING; } } public final boolean getHasFocus() { return mHasFocus; } public final Texture getHiResImage(Context context) { UriTexture texture = mHiResImage; if (texture == null) { texture = new UriTexture(mItemRef.mContentUri); texture.setCacheId(Utils.Crc64Long(mItemRef.mFilePath)); mHiResImage = texture; } return texture; } public boolean isAlive() { return mAlive; } public float getImageTheta() { return mImageTheta; } }