package org.anddev.andengine.opengl.texture.atlas.bitmap;
import java.util.ArrayList;
import javax.microedition.khronos.opengles.GL10;
import org.anddev.andengine.opengl.texture.TextureOptions;
import org.anddev.andengine.opengl.texture.atlas.TextureAtlas;
import org.anddev.andengine.opengl.texture.atlas.bitmap.source.IBitmapTextureAtlasSource;
import org.anddev.andengine.opengl.texture.bitmap.BitmapTexture.BitmapTextureFormat;
import org.anddev.andengine.opengl.texture.source.ITextureAtlasSource;
import org.anddev.andengine.opengl.util.GLHelper;
import org.anddev.andengine.util.Debug;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.opengl.GLUtils;
/**
* (c) 2010 Nicolas Gramlich
* (c) 2011 Zynga Inc.
*
* @author Nicolas Gramlich
* @since 14:55:02 - 08.03.2010
*/
public class BitmapTextureAtlas extends TextureAtlas<IBitmapTextureAtlasSource> {
// ===========================================================
// Constants
// ===========================================================
// ===========================================================
// Fields
// ===========================================================
private final BitmapTextureFormat mBitmapTextureFormat;
// ===========================================================
// Constructors
// ===========================================================
/**
* Uses {@link BitmapTextureFormat#RGBA_8888}.
*
* @param pWidth must be a power of 2 (i.e. 32, 64, 128, 256, 512, 1024).
* @param pHeight must be a power of 2 (i.e. 32, 64, 128, 256, 512, 1024).
*/
public BitmapTextureAtlas(final int pWidth, final int pHeight) {
this(pWidth, pHeight, BitmapTextureFormat.RGBA_8888);
}
/**
* @param pWidth must be a power of 2 (i.e. 32, 64, 128, 256, 512, 1024).
* @param pHeight must be a power of 2 (i.e. 32, 64, 128, 256, 512, 1024).
* @param pBitmapTextureFormat use {@link BitmapTextureFormat#RGBA_8888} for {@link BitmapTextureAtlas}MAGIC_CONSTANT with transparency and {@link BitmapTextureFormat#RGB_565} for {@link BitmapTextureAtlas}MAGIC_CONSTANT without transparency.
*/
public BitmapTextureAtlas(final int pWidth, final int pHeight, final BitmapTextureFormat pBitmapTextureFormat) {
this(pWidth, pHeight, pBitmapTextureFormat, TextureOptions.DEFAULT, null);
}
/**
* Uses {@link BitmapTextureFormat#RGBA_8888}.
*
* @param pWidth must be a power of 2 (i.e. 32, 64, 128, 256, 512, 1024).
* @param pHeight must be a power of 2 (i.e. 32, 64, 128, 256, 512, 1024).
* @param pTextureStateListener to be informed when this {@link BitmapTextureAtlas} is loaded, unloaded or a {@link ITextureAtlasSource} failed to load.
*/
public BitmapTextureAtlas(final int pWidth, final int pHeight, final ITextureAtlasStateListener<IBitmapTextureAtlasSource> pTextureAtlasStateListener) {
this(pWidth, pHeight, BitmapTextureFormat.RGBA_8888, TextureOptions.DEFAULT, pTextureAtlasStateListener);
}
/**
* @param pWidth must be a power of 2 (i.e. 32, 64, 128, 256, 512, 1024).
* @param pHeight must be a power of 2 (i.e. 32, 64, 128, 256, 512, 1024).
* @param pBitmapTextureFormat use {@link BitmapTextureFormat#RGBA_8888} for {@link BitmapTextureAtlas}MAGIC_CONSTANT with transparency and {@link BitmapTextureFormat#RGB_565} for {@link BitmapTextureAtlas}MAGIC_CONSTANT without transparency.
* @param pTextureAtlasStateListener to be informed when this {@link BitmapTextureAtlas} is loaded, unloaded or a {@link ITextureAtlasSource} failed to load.
*/
public BitmapTextureAtlas(final int pWidth, final int pHeight, final BitmapTextureFormat pBitmapTextureFormat, final ITextureAtlasStateListener<IBitmapTextureAtlasSource> pTextureAtlasStateListener) {
this(pWidth, pHeight, pBitmapTextureFormat, TextureOptions.DEFAULT, pTextureAtlasStateListener);
}
/**
* Uses {@link BitmapTextureFormat#RGBA_8888}.
*
* @param pWidth must be a power of 2 (i.e. 32, 64, 128, 256, 512, 1024).
* @param pHeight must be a power of 2 (i.e. 32, 64, 128, 256, 512, 1024).
* @param pTextureOptions the (quality) settings of the BitmapTexture.
*/
public BitmapTextureAtlas(final int pWidth, final int pHeight, final TextureOptions pTextureOptions) throws IllegalArgumentException {
this(pWidth, pHeight, BitmapTextureFormat.RGBA_8888, pTextureOptions, null);
}
/**
* @param pWidth must be a power of 2 (i.e. 32, 64, 128, 256, 512, 1024).
* @param pHeight must be a power of 2 (i.e. 32, 64, 128, 256, 512, 1024).
* @param pBitmapTextureFormat use {@link BitmapTextureFormat#RGBA_8888} for {@link BitmapTextureAtlas}MAGIC_CONSTANT with transparency and {@link BitmapTextureFormat#RGB_565} for {@link BitmapTextureAtlas}MAGIC_CONSTANT without transparency.
* @param pTextureOptions the (quality) settings of the BitmapTexture.
*/
public BitmapTextureAtlas(final int pWidth, final int pHeight, final BitmapTextureFormat pBitmapTextureFormat, final TextureOptions pTextureOptions) throws IllegalArgumentException {
this(pWidth, pHeight, pBitmapTextureFormat, pTextureOptions, null);
}
/**
* Uses {@link BitmapTextureFormat#RGBA_8888}.
*
* @param pWidth must be a power of 2 (i.e. 32, 64, 128, 256, 512, 1024).
* @param pHeight must be a power of 2 (i.e. 32, 64, 128, 256, 512, 1024).
* @param pTextureOptions the (quality) settings of the BitmapTexture.
* @param pTextureAtlasStateListener to be informed when this {@link BitmapTextureAtlas} is loaded, unloaded or a {@link ITextureAtlasSource} failed to load.
*/
public BitmapTextureAtlas(final int pWidth, final int pHeight, final TextureOptions pTextureOptions, final ITextureAtlasStateListener<IBitmapTextureAtlasSource> pTextureAtlasStateListener) throws IllegalArgumentException {
this(pWidth, pHeight, BitmapTextureFormat.RGBA_8888, pTextureOptions, pTextureAtlasStateListener);
}
/**
* @param pWidth must be a power of 2 (i.e. 32, 64, 128, 256, 512, 1024).
* @param pHeight must be a power of 2 (i.e. 32, 64, 128, 256, 512, 1024).
* @param pBitmapTextureFormat use {@link BitmapTextureFormat#RGBA_8888} for {@link BitmapTextureAtlas}MAGIC_CONSTANT with transparency and {@link BitmapTextureFormat#RGB_565} for {@link BitmapTextureAtlas}MAGIC_CONSTANT without transparency.
* @param pTextureOptions the (quality) settings of the BitmapTexture.
* @param pTextureAtlasStateListener to be informed when this {@link BitmapTextureAtlas} is loaded, unloaded or a {@link ITextureAtlasSource} failed to load.
*/
public BitmapTextureAtlas(final int pWidth, final int pHeight, final BitmapTextureFormat pBitmapTextureFormat, final TextureOptions pTextureOptions, final ITextureAtlasStateListener<IBitmapTextureAtlasSource> pTextureAtlasStateListener) throws IllegalArgumentException {
super(pWidth, pHeight, pBitmapTextureFormat.getPixelFormat(), pTextureOptions, pTextureAtlasStateListener);
this.mBitmapTextureFormat = pBitmapTextureFormat;
}
// ===========================================================
// Getter & Setter
// ===========================================================
public BitmapTextureFormat getBitmapTextureFormat() {
return this.mBitmapTextureFormat;
}
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
// ===========================================================
// Methods
// ===========================================================
@Override
protected void writeTextureToHardware(final GL10 pGL) {
final Config bitmapConfig = this.mBitmapTextureFormat.getBitmapConfig();
final int glFormat = this.mPixelFormat.getGLFormat();
final int glType = this.mPixelFormat.getGLType();
final boolean preMultipyAlpha = this.mTextureOptions.mPreMultipyAlpha;
final ArrayList<IBitmapTextureAtlasSource> textureSources = this.mTextureAtlasSources;
final int textureSourceCount = textureSources.size();
for(int j = 0; j < textureSourceCount; j++) {
final IBitmapTextureAtlasSource bitmapTextureAtlasSource = textureSources.get(j);
if(bitmapTextureAtlasSource != null) {
final Bitmap bitmap = bitmapTextureAtlasSource.onLoadBitmap(bitmapConfig);
try {
if(bitmap == null) {
throw new IllegalArgumentException(bitmapTextureAtlasSource.getClass().getSimpleName() + ": " + bitmapTextureAtlasSource.toString() + " returned a null Bitmap.");
}
if(preMultipyAlpha) {
GLUtils.texSubImage2D(GL10.GL_TEXTURE_2D, 0, bitmapTextureAtlasSource.getTexturePositionX(), bitmapTextureAtlasSource.getTexturePositionY(), bitmap, glFormat, glType);
} else {
GLHelper.glTexSubImage2D(pGL, GL10.GL_TEXTURE_2D, 0, bitmapTextureAtlasSource.getTexturePositionX(), bitmapTextureAtlasSource.getTexturePositionY(), bitmap, this.mPixelFormat);
}
bitmap.recycle();
} catch (final IllegalArgumentException iae) {
// TODO Load some static checkerboard or so to visualize that loading the texture has failed.
//private Buffer createImage(final int width, final int height) {
// final int stride = 3 * width;
// final ByteBuffer image = ByteBuffer.allocateDirect(height * stride)
// .order(ByteOrder.nativeOrder());
//
// // Fill with a pretty "munching squares" pattern:
// for (int t = 0; t < height; t++) {
// final byte red = (byte) (255 - 2 * t);
// final byte green = (byte) (2 * t);
// final byte blue = 0;
// for (int x = 0; x < width; x++) {
// final int y = x ^ t;
// image.position(stride * y + x * 3);
// image.put(red);
// image.put(green);
// image.put(blue);
// }
// }
// image.position(0);
// return image;
//}
Debug.e("Error loading: " + bitmapTextureAtlasSource.toString(), iae);
if(this.getTextureStateListener() != null) {
this.getTextureStateListener().onTextureAtlasSourceLoadExeption(this, bitmapTextureAtlasSource, iae);
} else {
throw iae;
}
}
}
}
}
@Override
protected void bindTextureOnHardware(final GL10 pGL) {
super.bindTextureOnHardware(pGL);
final PixelFormat pixelFormat = this.mBitmapTextureFormat.getPixelFormat();
final int glFormat = pixelFormat.getGLFormat();
final int glType = pixelFormat.getGLType();
pGL.glTexImage2D(GL10.GL_TEXTURE_2D, 0, glFormat, this.mWidth, this.mHeight, 0, glFormat, glType, null);
}
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
}