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/transitions | |
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/transitions')
6 files changed, 1092 insertions, 0 deletions
diff --git a/src/org/cyanogenmod/wallpapers/photophase/transitions/FadeTransition.java b/src/org/cyanogenmod/wallpapers/photophase/transitions/FadeTransition.java new file mode 100644 index 0000000..d88aafc --- /dev/null +++ b/src/org/cyanogenmod/wallpapers/photophase/transitions/FadeTransition.java @@ -0,0 +1,137 @@ +/* + * 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.transitions; + +import android.content.Context; +import android.opengl.GLException; +import android.os.SystemClock; + +import org.cyanogenmod.wallpapers.photophase.Colors; +import org.cyanogenmod.wallpapers.photophase.PhotoFrame; +import org.cyanogenmod.wallpapers.photophase.TextureManager; +import org.cyanogenmod.wallpapers.photophase.shapes.ColorShape; +import org.cyanogenmod.wallpapers.photophase.transitions.Transitions.TRANSITIONS; + +/** + * A transition that applies a fade transition to the picture. + */ +public class FadeTransition extends NullTransition { + + private static final float TRANSITION_TIME = 800.0f; + + private boolean mRunning; + private long mTime; + + ColorShape mOverlay; + + /** + * Constructor of <code>FadeTransition</code> + * + * @param ctx The current context + * @param tm The texture manager + */ + public FadeTransition(Context ctx, TextureManager tm) { + super(ctx, tm); + } + + /** + * {@inheritDoc} + */ + @Override + public TRANSITIONS getType() { + return TRANSITIONS.FADE; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean hasTransitionTarget() { + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isRunning() { + return mRunning; + } + + /** + * {@inheritDoc} + */ + @Override + public void reset() { + super.reset(); + mTime = -1; + mRunning = true; + } + + /** + * {@inheritDoc} + */ + @Override + public void select(PhotoFrame target) { + super.select(target); + mOverlay = new ColorShape(mContext, target.getPictureVertex(), Colors.getBackground()); + mOverlay.setAlpha(0); + } + + /** + * {@inheritDoc} + */ + @Override + public void apply(float[] matrix) throws GLException { + // Check internal vars + if (mTarget == null || + mTarget.getPictureVertexBuffer() == null || + mTarget.getTextureBuffer() == null || + mTarget.getVertexOrderBuffer() == null) { + return; + } + if (mTransitionTarget == null || + mTransitionTarget.getPictureVertexBuffer() == null || + mTransitionTarget.getTextureBuffer() == null || + mTransitionTarget.getVertexOrderBuffer() == null) { + return; + } + + // Set the time the first time + if (mTime == -1) { + mTime = SystemClock.uptimeMillis(); + } + + final float delta = Math.min(SystemClock.uptimeMillis() - mTime, TRANSITION_TIME) / TRANSITION_TIME; + if (delta <= 0.5) { + // Draw the src target + draw(mTarget, matrix); + mOverlay.setAlpha(delta * 2.0f); + } else { + // Draw the dst target + draw(mTransitionTarget, matrix); + mOverlay.setAlpha((1 - delta) * 2.0f); + } + mOverlay.draw(matrix); + + // Transition ended + if (delta == 1) { + mRunning = false; + } + } + +} diff --git a/src/org/cyanogenmod/wallpapers/photophase/transitions/NullTransition.java b/src/org/cyanogenmod/wallpapers/photophase/transitions/NullTransition.java new file mode 100644 index 0000000..66f89d1 --- /dev/null +++ b/src/org/cyanogenmod/wallpapers/photophase/transitions/NullTransition.java @@ -0,0 +1,182 @@ +/* + * 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.transitions; + +import android.content.Context; +import android.opengl.GLES20; +import android.opengl.GLException; + +import org.cyanogenmod.wallpapers.photophase.GLESUtil; +import org.cyanogenmod.wallpapers.photophase.PhotoFrame; +import org.cyanogenmod.wallpapers.photophase.R; +import org.cyanogenmod.wallpapers.photophase.TextureManager; +import org.cyanogenmod.wallpapers.photophase.transitions.Transitions.TRANSITIONS; + +import java.nio.FloatBuffer; +import java.nio.ShortBuffer; + +/** + * A special transition that does nothing other than draw the {@link PhotoFrame} + * on the screen continually. No transition is done. + */ +public class NullTransition extends Transition { + + private static final int[] VERTEX_SHADER = {R.raw.default_vertex_shader}; + private static final int[] FRAGMENT_SHADER = {R.raw.default_fragment_shader}; + + /** + * Constructor of <code>NullTransition</code> + * + * @param ctx The current context + * @param tm The texture manager + */ + public NullTransition(Context ctx, TextureManager tm) { + super(ctx, tm, VERTEX_SHADER, FRAGMENT_SHADER); + } + + /** + * {@inheritDoc} + */ + @Override + public void select(PhotoFrame target) { + super.select(target); + } + + /** + * {@inheritDoc} + */ + @Override + public TRANSITIONS getType() { + return TRANSITIONS.NO_TRANSITION; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean hasTransitionTarget() { + return false; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isRunning() { + return mTarget == null || !mTarget.isLoaded(); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isSelectable(PhotoFrame frame) { + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public void reset() { + // Nothing to do + } + + /** + * {@inheritDoc} + */ + @Override + public void apply(float[] matrix) throws GLException { + // Check internal vars + if (mTarget == null || + mTarget.getPictureVertexBuffer() == null || + mTarget.getTextureBuffer() == null || + mTarget.getVertexOrderBuffer() == null) { + return; + } + + // Draw the current target + draw(mTarget, matrix); + } + + /** + * Method that draws the picture texture + * + * @param target + * @param matrix The model-view-projection matrix + */ + protected void draw(PhotoFrame target, float[] matrix) { + // Set the program + useProgram(0); + + // Bind the texture + int textureHandle = target.getTextureHandle(); + GLES20.glActiveTexture(GLES20.GL_TEXTURE0); + GLESUtil.glesCheckError("glActiveTexture"); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle); + GLESUtil.glesCheckError("glBindTexture"); + + // Position + FloatBuffer vertexBuffer = target.getPictureVertexBuffer(); + vertexBuffer.position(0); + GLES20.glVertexAttribPointer( + mPositionHandlers[0], + PhotoFrame.COORDS_PER_VERTER, + GLES20.GL_FLOAT, + false, + PhotoFrame.COORDS_PER_VERTER * 4, + vertexBuffer); + GLESUtil.glesCheckError("glVertexAttribPointer"); + GLES20.glEnableVertexAttribArray(mPositionHandlers[0]); + GLESUtil.glesCheckError("glEnableVertexAttribArray"); + + // Texture + FloatBuffer textureBuffer = target.getTextureBuffer(); + textureBuffer.position(0); + GLES20.glVertexAttribPointer( + mTextureCoordHandlers[0], + 2, + GLES20.GL_FLOAT, + false, + 2 * 4, + textureBuffer); + GLESUtil.glesCheckError("glVertexAttribPointer"); + GLES20.glEnableVertexAttribArray(mTextureCoordHandlers[0]); + GLESUtil.glesCheckError("glEnableVertexAttribArray"); + + // Apply the projection and view transformation + GLES20.glUniformMatrix4fv(mMVPMatrixHandlers[0], 1, false, matrix, 0); + GLESUtil.glesCheckError("glUniformMatrix4fv"); + + // Draw the photo frame + ShortBuffer vertexOrderBuffer = target.getVertexOrderBuffer(); + vertexOrderBuffer.position(0); + GLES20.glDrawElements( + GLES20.GL_TRIANGLE_FAN, + 6, + GLES20.GL_UNSIGNED_SHORT, + vertexOrderBuffer); + GLESUtil.glesCheckError("glDrawElements"); + + // Disable attributes + GLES20.glDisableVertexAttribArray(mPositionHandlers[0]); + GLESUtil.glesCheckError("glDisableVertexAttribArray"); + GLES20.glDisableVertexAttribArray(mTextureCoordHandlers[0]); + GLESUtil.glesCheckError("glDisableVertexAttribArray"); + } + +} diff --git a/src/org/cyanogenmod/wallpapers/photophase/transitions/SwapTransition.java b/src/org/cyanogenmod/wallpapers/photophase/transitions/SwapTransition.java new file mode 100644 index 0000000..d100110 --- /dev/null +++ b/src/org/cyanogenmod/wallpapers/photophase/transitions/SwapTransition.java @@ -0,0 +1,113 @@ +/* + * 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.transitions; + +import android.content.Context; +import android.opengl.GLException; +import android.os.SystemClock; + +import org.cyanogenmod.wallpapers.photophase.TextureManager; +import org.cyanogenmod.wallpapers.photophase.transitions.Transitions.TRANSITIONS; + +/** + * A simple transition that swap an image after the transition time is ended. + */ +public class SwapTransition extends NullTransition { + + private static final float TRANSITION_TIME = 250.0f; + + private boolean mRunning; + private long mTime; + + /** + * Constructor of <code>SwapTransition</code> + * + * @param ctx The current context + * @param tm The texture manager + */ + public SwapTransition(Context ctx, TextureManager tm) { + super(ctx, tm); + } + + /** + * {@inheritDoc} + */ + @Override + public TRANSITIONS getType() { + return TRANSITIONS.SWAP; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean hasTransitionTarget() { + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isRunning() { + return mRunning; + } + + /** + * {@inheritDoc} + */ + @Override + public void reset() { + super.reset(); + mTime = -1; + mRunning = true; + } + + /** + * {@inheritDoc} + */ + @Override + public void apply(float[] matrix) throws GLException { + // Check internal vars + if (mTarget == null || + mTarget.getPictureVertexBuffer() == null || + mTarget.getTextureBuffer() == null || + mTarget.getVertexOrderBuffer() == null) { + return; + } + if (mTransitionTarget == null || + mTransitionTarget.getPictureVertexBuffer() == null || + mTransitionTarget.getTextureBuffer() == null || + mTransitionTarget.getVertexOrderBuffer() == null) { + return; + } + + // Set the time the first time + if (mTime == -1) { + mTime = SystemClock.uptimeMillis(); + } + + // Calculate the delta time + final float delta = Math.min(SystemClock.uptimeMillis() - mTime, TRANSITION_TIME) / TRANSITION_TIME; + + // Apply the transition + boolean ended = delta == 1; + draw(ended ? mTransitionTarget : mTarget, matrix); + mRunning = !ended; + } + +} diff --git a/src/org/cyanogenmod/wallpapers/photophase/transitions/Transition.java b/src/org/cyanogenmod/wallpapers/photophase/transitions/Transition.java new file mode 100644 index 0000000..315a9f8 --- /dev/null +++ b/src/org/cyanogenmod/wallpapers/photophase/transitions/Transition.java @@ -0,0 +1,202 @@ +/* + * 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.transitions; + +import android.content.Context; +import android.opengl.GLES20; + +import org.cyanogenmod.wallpapers.photophase.GLESUtil; +import org.cyanogenmod.wallpapers.photophase.PhotoFrame; +import org.cyanogenmod.wallpapers.photophase.TextureManager; +import org.cyanogenmod.wallpapers.photophase.transitions.Transitions.TRANSITIONS; + +/** + * The base class of all transitions that can be applied to the {@link PhotoFrame} classes. + */ +public abstract class Transition { + + public static final long MAX_TRANSTION_TIME = 1500L; + + protected final Context mContext; + private final TextureManager mTextureManager; + + protected int[] mProgramHandlers; + protected int[] mPositionHandlers; + protected int[] mTextureCoordHandlers; + protected int[] mMVPMatrixHandlers; + + protected PhotoFrame mTarget; + protected PhotoFrame mTransitionTarget; + + private final int[] mVertexShader; + private final int[] mFragmentShader; + + /** + * Constructor of <code>Transition</code> + * + * @param ctx The current context + * @param tm The current texture manager + * @param vertexShader The vertex shaders of the programs + * @param fragmentShader The fragment shaders of the programs + */ + public Transition(Context ctx, TextureManager tm, int[] vertexShader, int[] fragmentShader) { + super(); + mContext = ctx; + mTextureManager = tm; + mVertexShader = vertexShader; + mFragmentShader = fragmentShader; + + // Compile every program + assert mVertexShader.length != mFragmentShader.length; + int cc = mVertexShader.length; + mProgramHandlers = new int[cc]; + mPositionHandlers = new int[cc]; + mTextureCoordHandlers = new int[cc]; + mMVPMatrixHandlers = new int[cc]; + for (int i = 0; i < cc; i++) { + createProgram(i); + } + } + + /** + * Method that requests to apply this transition. + * + * @param target The target photo frame + */ + public void select(PhotoFrame target) { + mTarget = target; + if (hasTransitionTarget()) { + // Load the transition frame and request a picture for it + mTransitionTarget = + new PhotoFrame( + mContext, + mTextureManager, + mTarget.getFrameVertex(), + mTarget.getPictureVertex(), + mTarget.getBackgroundColor()); + } + } + + /** + * Method that returns the target of the transition. + * + * @return PhotoFrame The target of the transition + */ + public PhotoFrame getTarget() { + return mTarget; + } + + /** + * Method that returns the transition target of the transition. + * + * @return PhotoFrame The transition target of the transition + */ + public PhotoFrame getTransitionTarget() { + return mTransitionTarget; + } + + /** + * Method that returns if the transition is selectable for the passed frame. + * + * @param frame The frame which the transition should be applied to + * @return boolean If the transition is selectable for the passed frame + */ + public abstract boolean isSelectable(PhotoFrame frame); + + /** + * Method that resets the current status of the transition. + */ + public abstract void reset(); + + /** + * Method that returns the type of transition. + * + * @return TRANSITIONS The type of transition + */ + public abstract TRANSITIONS getType(); + + /** + * Method that requests to apply this transition. + * + * @param matrix The model-view-projection matrix + */ + public abstract void apply(float[] matrix); + + /** + * Method that returns if the transition is being transition. + * + * @return boolean If the transition is being transition. + */ + public abstract boolean isRunning(); + + /** + * Method that return if the transition has a secondary target + * + * @return boolean If the transition has a secondary target + */ + public abstract boolean hasTransitionTarget(); + + /** + * Method that creates the program + */ + protected void createProgram(int index) { + mProgramHandlers[index] = + GLESUtil.createProgram( + mContext.getResources(), mVertexShader[index], mFragmentShader[index]); + mPositionHandlers[index] = + GLES20.glGetAttribLocation(mProgramHandlers[index], "aPosition"); + GLESUtil.glesCheckError("glGetAttribLocation"); + mTextureCoordHandlers[index] = + GLES20.glGetAttribLocation(mProgramHandlers[index], "aTextureCoord"); + GLESUtil.glesCheckError("glGetAttribLocation"); + mMVPMatrixHandlers[index] = + GLES20.glGetUniformLocation(mProgramHandlers[index], "uMVPMatrix"); + GLESUtil.glesCheckError("glGetUniformLocation"); + } + + /** + * Method that set the program to use + * + * @param index The index of the program to use + */ + protected void useProgram(int index) { + if (!GLES20.glIsProgram(mProgramHandlers[index])) { + createProgram(index); + } + GLES20.glUseProgram(mProgramHandlers[index]); + GLESUtil.glesCheckError("glUseProgram(" + index + ")"); + } + + /** + * Method that requests to the transition to remove its internal references and resources. + */ + public void recycle() { + int cc = mProgramHandlers.length; + for (int i = 0; i < cc; i++) { + if (GLES20.glIsProgram(mProgramHandlers[i])) { + GLES20.glDeleteProgram(mProgramHandlers[i]); + GLESUtil.glesCheckError("glDeleteProgram"); + } + mProgramHandlers[i] = 0; + mPositionHandlers[i] = 0; + mTextureCoordHandlers[i] = 0; + mMVPMatrixHandlers[i] = 0; + } + mTransitionTarget = null; + mTarget = null; + } +} diff --git a/src/org/cyanogenmod/wallpapers/photophase/transitions/Transitions.java b/src/org/cyanogenmod/wallpapers/photophase/transitions/Transitions.java new file mode 100644 index 0000000..e29bfce --- /dev/null +++ b/src/org/cyanogenmod/wallpapers/photophase/transitions/Transitions.java @@ -0,0 +1,104 @@ +/* + * 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.transitions; + +import android.content.Context; + +import org.cyanogenmod.wallpapers.photophase.PhotoFrame; +import org.cyanogenmod.wallpapers.photophase.TextureManager; +import org.cyanogenmod.wallpapers.photophase.preferences.PreferencesProvider.Preferences; + + +/** + * A class that manages all the supported transitions + */ +public class Transitions { + + /** + * Enumeration of the supported transitions + */ + public enum TRANSITIONS { + /** + * A random combination of all supported transitions + */ + RANDOM, + /** + * @see NullTransition + */ + NO_TRANSITION, + /** + * @see SwapTransition + */ + SWAP, + /** + * @see FadeTransition + */ + FADE, + /** + * @see TranslateTransition + */ + TRANSLATION; + } + + /** + * Method that return the next type of transition to apply the picture. + * + * @param frame The frame which the effect will be applied to + * @return TRANSITIONS The next type of transition to apply + */ + public static TRANSITIONS getNextTypeOfTransition(PhotoFrame frame) { + int transition = Preferences.General.Transitions.getTransitionTypes(); + if (transition == TRANSITIONS.RANDOM.ordinal()) { + int low = TRANSITIONS.SWAP.ordinal(); + int hight = TRANSITIONS.values().length - 1; + transition = low + (int)(Math.random() * ((hight - low) + 1)); + } + if (transition == TRANSITIONS.SWAP.ordinal()) { + return TRANSITIONS.SWAP; + } + if (transition == TRANSITIONS.FADE.ordinal()) { + return TRANSITIONS.FADE; + } + if (transition == TRANSITIONS.TRANSLATION.ordinal()) { + return TRANSITIONS.TRANSLATION; + } + return TRANSITIONS.NO_TRANSITION; + } + + /** + * Method that creates a new transition. + * + * @param ctx The current context + * @param tm The texture manager + * @param type The type of transition + * @param frame The frame which the effect will be applied to + * @return Transition The next transition to apply + */ + public static Transition createTransition( + Context ctx, TextureManager tm, TRANSITIONS type, PhotoFrame frame) { + if (type.compareTo(TRANSITIONS.SWAP) == 0) { + return new SwapTransition(ctx, tm); + } + if (type.compareTo(TRANSITIONS.FADE) == 0) { + return new FadeTransition(ctx, tm); + } + if (type.compareTo(TRANSITIONS.TRANSLATION) == 0) { + return new TranslateTransition(ctx, tm); + } + return new NullTransition(ctx, tm); + } +} diff --git a/src/org/cyanogenmod/wallpapers/photophase/transitions/TranslateTransition.java b/src/org/cyanogenmod/wallpapers/photophase/transitions/TranslateTransition.java new file mode 100644 index 0000000..4e32a4a --- /dev/null +++ b/src/org/cyanogenmod/wallpapers/photophase/transitions/TranslateTransition.java @@ -0,0 +1,354 @@ +/* + * 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.transitions; + +import android.content.Context; +import android.opengl.GLES20; +import android.opengl.GLException; +import android.opengl.Matrix; +import android.os.SystemClock; + +import org.cyanogenmod.wallpapers.photophase.GLESUtil; +import org.cyanogenmod.wallpapers.photophase.PhotoFrame; +import org.cyanogenmod.wallpapers.photophase.R; +import org.cyanogenmod.wallpapers.photophase.TextureManager; +import org.cyanogenmod.wallpapers.photophase.transitions.Transitions.TRANSITIONS; + +import java.nio.FloatBuffer; +import java.nio.ShortBuffer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * A transition that applies a translation transition to the picture. + */ +public class TranslateTransition extends Transition { + + /** + * The enumeration of all possibles translations movements + */ + public enum TRANSLATE_MODES { + /** + * Translate the picture from left to right + */ + LEFT_TO_RIGHT, + /** + * Translate the picture from right to left + */ + RIGHT_TO_LEFT, + /** + * Translate the picture from up to down + */ + UP_TO_DOWN, + /** + * Translate the picture from down to up + */ + DOWN_TO_UP + } + + private static final int[] VERTEX_SHADER = {R.raw.translate_vertex_shader, R.raw.default_vertex_shader}; + private static final int[] FRAGMENT_SHADER = {R.raw.translate_fragment_shader, R.raw.default_fragment_shader}; + + private static final float TRANSITION_TIME = 800.0f; + + private TRANSLATE_MODES mMode; + + private boolean mRunning; + private long mTime; + + /** + * Constructor of <code>TranslateTransition</code> + * + * @param ctx The current context + * @param tm The texture manager + */ + public TranslateTransition(Context ctx, TextureManager tm) { + super(ctx, tm, VERTEX_SHADER, FRAGMENT_SHADER); + + // Initialized + reset(); + } + + /** + * {@inheritDoc} + */ + @Override + public TRANSITIONS getType() { + return TRANSITIONS.TRANSLATION; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean hasTransitionTarget() { + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isRunning() { + return mRunning; + } + + /** + * {@inheritDoc} + */ + @Override + public void select(PhotoFrame target) { + super.select(target); + + // Discard all non-supported modes + List<TRANSLATE_MODES> modes = + new ArrayList<TranslateTransition.TRANSLATE_MODES>( + Arrays.asList(TRANSLATE_MODES.values())); + float[] vertex = target.getFrameVertex(); + if (vertex[0] != -1.0f) { + modes.remove(TRANSLATE_MODES.RIGHT_TO_LEFT); + } + if (vertex[9] != 1.0f) { + modes.remove(TRANSLATE_MODES.LEFT_TO_RIGHT); + } + if (vertex[1] != 1.0f) { + modes.remove(TRANSLATE_MODES.DOWN_TO_UP); + } + if (vertex[4] != -1.0f) { + modes.remove(TRANSLATE_MODES.UP_TO_DOWN); + } + + // Random mode + int low = 0; + int hight = modes.size() - 1; + mMode = modes.get(low + (int)(Math.random() * ((hight - low) + 1))); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isSelectable(PhotoFrame frame) { + float[] vertex = frame.getFrameVertex(); + if (vertex[0] == -1.0f || vertex[9] == 1.0f || + vertex[1] == 1.0f || vertex[4] == -1.0f) { + return true; + } + return false; + } + + /** + * {@inheritDoc} + */ + @Override + public void reset() { + mTime = -1; + mRunning = true; + } + + /** + * {@inheritDoc} + */ + @Override + public void apply(float[] matrix) throws GLException { + // Check internal vars + if (mTarget == null || + mTarget.getPictureVertexBuffer() == null || + mTarget.getTextureBuffer() == null || + mTarget.getVertexOrderBuffer() == null) { + return; + } + if (mTransitionTarget == null || + mTransitionTarget.getPictureVertexBuffer() == null || + mTransitionTarget.getTextureBuffer() == null || + mTransitionTarget.getVertexOrderBuffer() == null) { + return; + } + + // Set the time the first time + if (mTime == -1) { + mTime = SystemClock.uptimeMillis(); + } + + // Calculate the delta time + final float delta = Math.min(SystemClock.uptimeMillis() - mTime, TRANSITION_TIME) / TRANSITION_TIME; + + // Apply the transition + applyTransitionToTransitionTarget(delta, matrix); + if (delta < 1) { + applyTransitionToTarget(delta, matrix); + } + + // Transition ending + if (delta == 1) { + mRunning = false; + } + } + + /** + * Apply the transition to the passed frame + * + * @param delta The delta time + * @param matrix The model-view-projection matrix + */ + private void applyTransitionToTarget(float delta, float[] matrix) { + // Set the program + useProgram(0); + + // Bind the texture + int textureHandle = mTarget.getTextureHandle(); + GLES20.glActiveTexture(GLES20.GL_TEXTURE0); + GLESUtil.glesCheckError("glActiveTexture"); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle); + GLESUtil.glesCheckError("glBindTexture"); + + // Position + FloatBuffer vertexBuffer = mTarget.getPictureVertexBuffer(); + vertexBuffer.position(0); + GLES20.glVertexAttribPointer( + mPositionHandlers[0], + PhotoFrame.COORDS_PER_VERTER, + GLES20.GL_FLOAT, + false, + PhotoFrame.COORDS_PER_VERTER * 4, + vertexBuffer); + GLESUtil.glesCheckError("glVertexAttribPointer"); + GLES20.glEnableVertexAttribArray(mPositionHandlers[0]); + GLESUtil.glesCheckError("glEnableVertexAttribArray"); + + // Texture + FloatBuffer textureBuffer = mTarget.getTextureBuffer(); + textureBuffer.position(0); + GLES20.glVertexAttribPointer( + mTextureCoordHandlers[0], + 2, + GLES20.GL_FLOAT, + false, + 2 * 4, + textureBuffer); + GLESUtil.glesCheckError("glVertexAttribPointer"); + GLES20.glEnableVertexAttribArray(mTextureCoordHandlers[0]); + GLESUtil.glesCheckError("glEnableVertexAttribArray"); + + // Calculate the delta distance + float distance = + (mMode.compareTo(TRANSLATE_MODES.LEFT_TO_RIGHT) == 0 || mMode.compareTo(TRANSLATE_MODES.RIGHT_TO_LEFT) == 0) + ? mTarget.getPictureWidth() + : mTarget.getPictureHeight(); + if (mMode.compareTo(TRANSLATE_MODES.RIGHT_TO_LEFT) == 0 || mMode.compareTo(TRANSLATE_MODES.DOWN_TO_UP) == 0) { + distance *= -1; + } + distance *= delta; + boolean vertical = (mMode.compareTo(TRANSLATE_MODES.UP_TO_DOWN) == 0 || mMode.compareTo(TRANSLATE_MODES.DOWN_TO_UP) == 0); + + // Apply the projection and view transformation + float[] translationMatrix = new float[16]; + if (vertical) { + Matrix.translateM(translationMatrix, 0, matrix, 0, 0.0f, distance, 0.0f); + } else { + Matrix.translateM(translationMatrix, 0, matrix, 0, distance, 0.0f, 0.0f); + } + GLES20.glUniformMatrix4fv(mMVPMatrixHandlers[0], 1, false, translationMatrix, 0); + GLESUtil.glesCheckError("glUniformMatrix4fv"); + + // Draw the photo frame + ShortBuffer vertexOrderBuffer = mTarget.getVertexOrderBuffer(); + vertexOrderBuffer.position(0); + GLES20.glDrawElements( + GLES20.GL_TRIANGLE_FAN, + 6, + GLES20.GL_UNSIGNED_SHORT, + vertexOrderBuffer); + GLESUtil.glesCheckError("glDrawElements"); + + // Disable attributes + GLES20.glDisableVertexAttribArray(mPositionHandlers[0]); + GLESUtil.glesCheckError("glDisableVertexAttribArray"); + GLES20.glDisableVertexAttribArray(mTextureCoordHandlers[0]); + GLESUtil.glesCheckError("glDisableVertexAttribArray"); + } + + /** + * Apply the transition to the passed frame + * + * @param delta The delta time + * @param matrix The model-view-projection matrix + */ + private void applyTransitionToTransitionTarget(float delta, float[] matrix) { + // Set the program + useProgram(1); + + // Bind the texture + int textureHandle = mTransitionTarget.getTextureHandle(); + GLES20.glActiveTexture(GLES20.GL_TEXTURE0); + GLESUtil.glesCheckError("glActiveTexture"); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle); + GLESUtil.glesCheckError("glBindTexture"); + + // Position + FloatBuffer vertexBuffer = mTransitionTarget.getPictureVertexBuffer(); + vertexBuffer.position(0); + GLES20.glVertexAttribPointer( + mPositionHandlers[1], + PhotoFrame.COORDS_PER_VERTER, + GLES20.GL_FLOAT, + false, + PhotoFrame.COORDS_PER_VERTER * 4, + vertexBuffer); + GLESUtil.glesCheckError("glVertexAttribPointer"); + GLES20.glEnableVertexAttribArray(mPositionHandlers[1]); + GLESUtil.glesCheckError("glEnableVertexAttribArray"); + + // Texture + FloatBuffer textureBuffer = mTransitionTarget.getTextureBuffer(); + textureBuffer.position(0); + GLES20.glVertexAttribPointer( + mTextureCoordHandlers[1], + 2, + GLES20.GL_FLOAT, + false, + 2 * 4, + textureBuffer); + GLESUtil.glesCheckError("glVertexAttribPointer"); + GLES20.glEnableVertexAttribArray(mTextureCoordHandlers[1]); + GLESUtil.glesCheckError("glEnableVertexAttribArray"); + + // Apply the projection and view transformation + float[] translationMatrix = new float[16]; + Matrix.translateM(translationMatrix, 0, matrix, 0, 0.0f, 0.0f, 0.0f); + GLES20.glUniformMatrix4fv(mMVPMatrixHandlers[1], 1, false, translationMatrix, 0); + GLESUtil.glesCheckError("glUniformMatrix4fv"); + + // Draw the photo frame + ShortBuffer vertexOrderBuffer = mTransitionTarget.getVertexOrderBuffer(); + vertexOrderBuffer.position(0); + GLES20.glDrawElements( + GLES20.GL_TRIANGLE_FAN, + 6, + GLES20.GL_UNSIGNED_SHORT, + vertexOrderBuffer); + GLESUtil.glesCheckError("glDrawElements"); + + // Disable attributes + GLES20.glDisableVertexAttribArray(mPositionHandlers[1]); + GLESUtil.glesCheckError("glDisableVertexAttribArray"); + GLES20.glDisableVertexAttribArray(mTextureCoordHandlers[1]); + GLESUtil.glesCheckError("glDisableVertexAttribArray"); + } + +} |