aboutsummaryrefslogtreecommitdiffstats
path: root/src/org/cyanogenmod/wallpapers/photophase/PhotoPhaseWallpaperWorld.java
diff options
context:
space:
mode:
authorjruesga <jorge@ruesga.com>2013-07-01 02:42:54 +0200
committerjruesga <jorge@ruesga.com>2013-07-01 02:42:54 +0200
commitf29d68d929061ccbb982019c5020be721bbef862 (patch)
tree24ce41fb0dd7f942ca9dbe956fe93fe836da66c2 /src/org/cyanogenmod/wallpapers/photophase/PhotoPhaseWallpaperWorld.java
downloadandroid_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.java353
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;
+ }
+}