diff options
author | jruesga <jorge@ruesga.com> | 2013-07-01 02:42:54 +0200 |
---|---|---|
committer | jruesga <jorge@ruesga.com> | 2013-07-01 02:42:54 +0200 |
commit | f29d68d929061ccbb982019c5020be721bbef862 (patch) | |
tree | 24ce41fb0dd7f942ca9dbe956fe93fe836da66c2 /src/org/cyanogenmod/wallpapers/photophase/PhotoPhaseWallpaperWorld.java | |
download | android_packages_wallpapers_PhotoPhase-f29d68d929061ccbb982019c5020be721bbef862.tar.gz android_packages_wallpapers_PhotoPhase-f29d68d929061ccbb982019c5020be721bbef862.tar.bz2 android_packages_wallpapers_PhotoPhase-f29d68d929061ccbb982019c5020be721bbef862.zip |
Initial commit
Signed-off-by: jruesga <jorge@ruesga.com>
Diffstat (limited to 'src/org/cyanogenmod/wallpapers/photophase/PhotoPhaseWallpaperWorld.java')
-rw-r--r-- | src/org/cyanogenmod/wallpapers/photophase/PhotoPhaseWallpaperWorld.java | 353 |
1 files changed, 353 insertions, 0 deletions
diff --git a/src/org/cyanogenmod/wallpapers/photophase/PhotoPhaseWallpaperWorld.java b/src/org/cyanogenmod/wallpapers/photophase/PhotoPhaseWallpaperWorld.java new file mode 100644 index 0000000..395cdbb --- /dev/null +++ b/src/org/cyanogenmod/wallpapers/photophase/PhotoPhaseWallpaperWorld.java @@ -0,0 +1,353 @@ +/* + * Copyright (C) 2013 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.cyanogenmod.wallpapers.photophase; + +import android.content.Context; +import android.content.res.Configuration; +import android.util.Log; + +import org.cyanogenmod.wallpapers.photophase.preferences.Disposition; +import org.cyanogenmod.wallpapers.photophase.preferences.PreferencesProvider.Preferences; +import org.cyanogenmod.wallpapers.photophase.transitions.Transition; +import org.cyanogenmod.wallpapers.photophase.transitions.Transitions; +import org.cyanogenmod.wallpapers.photophase.transitions.Transitions.TRANSITIONS; + +import java.util.ArrayList; +import java.util.List; + +/** + * A class that represents the wallpapers with all its photo frames. + */ +public class PhotoPhaseWallpaperWorld { + + private static final String TAG = "PhotoPhaseWallpaperWorld"; + + private static final boolean DEBUG = false; + + // The frame padding + private static final int PHOTO_FRAME_PADDING = 2; + + private final Context mContext; + private final TextureManager mTextureManager; + + private List<PhotoFrame> mPhotoFrames; + private List<Transition> mTransitions; + private final List<Transition> mUnusedTransitions; + + private List<Integer> mTransitionsQueue; + private List<Integer> mUsedTransitionsQueue; + private int mCurrent; + + private boolean mRecycled; + + /** + * Constructor <code>PhotoPhaseWallpaperWorld</code> + * + * @param ctx The current context + * @param textureManager The texture manager + */ + public PhotoPhaseWallpaperWorld( + Context ctx, TextureManager textureManager) { + super(); + mContext = ctx; + mTextureManager = textureManager; + mCurrent = -1; + mUnusedTransitions = new ArrayList<Transition>(); + mRecycled = false; + } + + /** + * Method that returns an unused transition for the type of transition + * + * @param type The type of transition + * @return Transition The unused transition + */ + private Transition getUnusedTransition(TRANSITIONS type) { + for (Transition transition : mUnusedTransitions) { + if (transition.getType().compareTo(type) == 0) { + mUnusedTransitions.remove(transition); + return transition; + } + } + return null; + } + + /** + * Method that returns or creates a transition for the type of transition + * + * @param type The type of transition + * @param frame The frame which the effect will be applied to + * @return Transition The unused transition + */ + private Transition getOrCreateTransition(TRANSITIONS type, PhotoFrame frame) { + Transition transition = getUnusedTransition(type); + if (transition == null) { + transition = Transitions.createTransition(mContext, mTextureManager, type, frame); + } + transition.reset(); + return transition; + } + + /** + * Method that selects a transition and assign it to a photo frame. + */ + public void selectTransition() { + // Ensure queue + if (mTransitionsQueue.isEmpty()) { + mTransitionsQueue.addAll(mUsedTransitionsQueue); + mUsedTransitionsQueue.clear(); + } + + // Get a random frame to which apply the transition + int r = 0 + (int)(Math.random() * (((mTransitionsQueue.size()-1) - 0) + 1)); + int pos = mTransitionsQueue.remove(r).intValue(); + mUsedTransitionsQueue.add(Integer.valueOf(pos)); + + // Create or use a transition + PhotoFrame frame = mPhotoFrames.get(pos); + Transition transition = null; + boolean isSelectable = false; + while (transition == null || !isSelectable) { + boolean isRandom = Preferences.General.Transitions.getTransitionTypes() == TRANSITIONS.RANDOM.ordinal(); + TRANSITIONS type = Transitions.getNextTypeOfTransition(frame); + transition = getOrCreateTransition(type, frame); + isSelectable = transition.isSelectable(frame); + if (!isSelectable) { + mUnusedTransitions.add(transition); + if (!isRandom) { + // If is not possible to select a valid transition then select a swap + // transition (this one doesn't relies on any selection) + transition = getOrCreateTransition(TRANSITIONS.SWAP, frame); + isSelectable = true; + } + } + } + mTransitions.set(pos, transition); + transition.select(frame); + mCurrent = pos; + } + + /** + * Method that deselect the current transition. + * + * @param matrix The model-view-projection matrix + */ + public void deselectTransition(float[] matrix) { + if (mCurrent != -1) { + // Retrieve the finally target + Transition currentTransition = mTransitions.get(mCurrent); + PhotoFrame currentTarget = currentTransition.getTarget(); + PhotoFrame finalTarget = currentTransition.getTransitionTarget(); + mUnusedTransitions.add(currentTransition); + + if (finalTarget != null) { + Transition transition = getOrCreateTransition(TRANSITIONS.NO_TRANSITION, finalTarget); + mTransitions.set(mCurrent, transition); + + currentTarget.recycle(); + mPhotoFrames.set(mCurrent, finalTarget); + transition.select(finalTarget); + + // Draw the transition once + transition.apply(matrix); + } + mCurrent = -1; + } + } + + /** + * Method that removes all internal references. + */ + public void recycle() { + // Destroy the previous world + if (mTransitions != null) { + int cc = mTransitions.size()-1; + for (int i = cc; i >= 0; i--) { + Transition transition = mTransitions.get(i); + transition.recycle(); + mTransitions.remove(i); + } + } + if (mUnusedTransitions != null) { + int cc = mUnusedTransitions.size()-1; + for (int i = cc; i >= 0; i--) { + Transition transition = mUnusedTransitions.get(i); + transition.recycle(); + mUnusedTransitions.remove(i); + } + } + if (mPhotoFrames != null) { + int cc = mPhotoFrames.size()-1; + for (int i = cc; i >= 0; i--) { + PhotoFrame frame = mPhotoFrames.get(i); + mTextureManager.releaseBitmap(frame.getTextureBitmap()); + frame.recycle(); + mPhotoFrames.remove(i); + } + } + mTransitionsQueue.clear(); + mUsedTransitionsQueue.clear(); + mRecycled = true; + } + + /** + * Method that returns if there are any transition running in the world. + * + * @return boolean If there are any transition running in the world + */ + public boolean hasRunningTransition() { + if (mTransitions != null) { + for (Transition transition : mTransitions) { + if (transition.isRunning()) { + return true; + } + } + } + return false; + } + + /** + * Method that creates and fills the world with {@link PhotoFrame} objects. + * + * @param w The new width dimension + * @param h The new height dimension + */ + public synchronized void recreateWorld(int w, int h) { + if (DEBUG) Log.d(TAG, "Recreating the world. New surface: " + w + "x" + h); + + // Destroy the previous world + if (mRecycled) { + recycle(); + mRecycled = false; + } + + // Calculate the new world + int orientation = mContext.getResources().getConfiguration().orientation; + boolean portrait = orientation == Configuration.ORIENTATION_PORTRAIT; + int cols = portrait ? Preferences.Layout.getCols() : Preferences.Layout.getRows(); + int rows = portrait ? Preferences.Layout.getRows() : Preferences.Layout.getCols(); + float cellw = 2.0f / cols; + float cellh = 2.0f / rows; + List<Disposition> dispositions = Preferences.Layout.getDisposition(); + if (DEBUG) Log.d(TAG, + "Dispositions: " + dispositions.size() + " | " + String.valueOf(dispositions)); + mPhotoFrames = new ArrayList<PhotoFrame>(dispositions.size()); + mTransitions = new ArrayList<Transition>(dispositions.size()); + mTransitionsQueue = new ArrayList<Integer>(dispositions.size()); + mUsedTransitionsQueue = new ArrayList<Integer>(dispositions.size()); + int i = 0; + for (Disposition disposition : dispositions) { + // Create the photo frame + float[] frameVertices = getVerticesFromDisposition(disposition, portrait, cellw, cellh); + float[] pictureVertices = getFramePadding(frameVertices, portrait ? w : h, portrait ? h : w); + PhotoFrame frame = + new PhotoFrame( + mContext, + mTextureManager, + frameVertices, + pictureVertices, + Colors.getBackground()); + mPhotoFrames.add(frame); + + // Assign a null transition to the photo frame + Transition transition = getOrCreateTransition(TRANSITIONS.NO_TRANSITION, frame); + transition.select(frame); + mTransitions.add(transition); + + mTransitionsQueue.add(Integer.valueOf(i)); + i++; + } + } + + /** + * Method that draws all the photo frames. + * + * @param matrix The model-view-projection matrix + */ + public void draw(float[] matrix) { + // Apply every transition + if (mTransitions != null) { + // First draw active transitions; then the not running transitions + for (Transition transition : mTransitions) { + transition.apply(matrix); + } + } + } + + /** + * Method that returns a coordinates per vertex array from a disposition + * + * @param disposition The source disposition + * @param portrait If the device is in portrait mode + * @param cellw The cell width based on the surface + * @param cellh The cell height based on the surface + * @return float[] The coordinates per vertex array + */ + private static float[] getVerticesFromDisposition( + Disposition disposition, boolean portrait, float cellw, float cellh) { + int x = portrait ? disposition.x : disposition.y; + int y = portrait ? disposition.y : disposition.x; + int w = portrait ? disposition.w : disposition.h; + int h = portrait ? disposition.h : disposition.w; + return new float[] + { + // top left + -1.0f + (x * cellw), + 1.0f - (y * cellh), + 0.0f, + + // bottom left + -1.0f + (x * cellw), + 1.0f - ((y * cellh) + (h * cellh)), + 0.0f, + + // bottom right + -1.0f + ((x * cellw) + (w * cellw)), + 1.0f - ((y * cellh) + (h * cellh)), + 0.0f, + + // top right + -1.0f + ((x * cellw) + (w * cellw)), + 1.0f - (y * cellh), + 0.0f + }; + } + + /** + * Method that applies a padding to the frame + * + * @param texCoords The source coordinates + * @param screenWidth The screen width + * @param screenHeight The screen height + * @return float[] The new coordinates + */ + private static float[] getFramePadding(float[] coords, int screenWidth, int screenHeight) { + float[] paddingCoords = new float[coords.length]; + System.arraycopy(coords, 0, paddingCoords, 0, coords.length); + final float pxw = (1 / (float)screenWidth) * PHOTO_FRAME_PADDING; + final float pxh = (1 / (float)screenHeight) * PHOTO_FRAME_PADDING; + paddingCoords[0] += pxw; + paddingCoords[1] -= pxh; + paddingCoords[3] += pxw; + paddingCoords[4] += pxh; + paddingCoords[6] -= pxw; + paddingCoords[7] += pxh; + paddingCoords[9] -= pxw; + paddingCoords[10] -= pxh; + return paddingCoords; + } +} |