package org.anddev.andengine.entity.shape;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;
import org.anddev.andengine.engine.camera.Camera;
import org.anddev.andengine.entity.Entity;
import org.anddev.andengine.input.touch.TouchEvent;
import org.anddev.andengine.opengl.buffer.BufferObjectManager;
import org.anddev.andengine.opengl.util.GLHelper;
import org.anddev.andengine.opengl.vertex.VertexBuffer;
/**
* (c) 2010 Nicolas Gramlich
* (c) 2011 Zynga Inc.
*
* @author Nicolas Gramlich
* @since 11:51:27 - 13.03.2010
*/
public abstract class Shape extends Entity implements IShape {
// ===========================================================
// Constants
// ===========================================================
public static final int BLENDFUNCTION_SOURCE_DEFAULT = GL10.GL_SRC_ALPHA;
public static final int BLENDFUNCTION_DESTINATION_DEFAULT = GL10.GL_ONE_MINUS_SRC_ALPHA;
public static final int BLENDFUNCTION_SOURCE_PREMULTIPLYALPHA_DEFAULT = GL10.GL_ONE;
public static final int BLENDFUNCTION_DESTINATION_PREMULTIPLYALPHA_DEFAULT = GL10.GL_ONE_MINUS_SRC_ALPHA;
// ===========================================================
// Fields
// ===========================================================
protected int mSourceBlendFunction = BLENDFUNCTION_SOURCE_DEFAULT;
protected int mDestinationBlendFunction = BLENDFUNCTION_DESTINATION_DEFAULT;
private boolean mCullingEnabled = false;
// ===========================================================
// Constructors
// ===========================================================
public Shape(final float pX, final float pY) {
super(pX, pY);
}
// ===========================================================
// Getter & Setter
// ===========================================================
@Override
public void setBlendFunction(final int pSourceBlendFunction, final int pDestinationBlendFunction) {
this.mSourceBlendFunction = pSourceBlendFunction;
this.mDestinationBlendFunction = pDestinationBlendFunction;
}
@Override
public boolean isCullingEnabled() {
return this.mCullingEnabled;
}
@Override
public void setCullingEnabled(final boolean pCullingEnabled) {
this.mCullingEnabled = pCullingEnabled;
}
@Override
public float getWidthScaled() {
return this.getWidth() * this.mScaleX;
}
@Override
public float getHeightScaled() {
return this.getHeight() * this.mScaleY;
}
public boolean isVertexBufferManaged() {
return this.getVertexBuffer().isManaged();
}
/**
* @param pVertexBufferManaged when passing <code>true</code> this {@link Shape} will make its {@link VertexBuffer} unload itself from the active {@link BufferObjectManager}, when this {@link Shape} is finalized/garbage-collected. <b><u>WARNING:</u></b> When passing <code>false</code> one needs to take care of that by oneself!
*/
public void setVertexBufferManaged(final boolean pVertexBufferManaged) {
this.getVertexBuffer().setManaged(pVertexBufferManaged);
}
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
protected abstract void onUpdateVertexBuffer();
protected abstract VertexBuffer getVertexBuffer();
protected abstract void drawVertices(final GL10 pGL, final Camera pCamera);
@Override
protected void doDraw(final GL10 pGL, final Camera pCamera) {
this.onInitDraw(pGL);
this.onApplyVertices(pGL);
this.drawVertices(pGL, pCamera);
}
@Override
public boolean onAreaTouched(final TouchEvent pSceneTouchEvent, final float pTouchAreaLocalX, final float pTouchAreaLocalY) {
return false;
}
/**
* Will only be performed if {@link Shape#isCullingEnabled()} is true.
* @param pCamera
* @return <code>true</code> when this object is visible by the {@link Camera}, <code>false</code> otherwise.
*/
protected abstract boolean isCulled(final Camera pCamera);
@Override
protected void onManagedDraw(final GL10 pGL, final Camera pCamera) {
if(!this.mCullingEnabled || !this.isCulled(pCamera)) {
super.onManagedDraw(pGL, pCamera);
}
}
@Override
public void reset() {
super.reset();
this.mSourceBlendFunction = BLENDFUNCTION_SOURCE_DEFAULT;
this.mDestinationBlendFunction = BLENDFUNCTION_DESTINATION_DEFAULT;
}
@Override
protected void finalize() throws Throwable {
super.finalize();
final VertexBuffer vertexBuffer = this.getVertexBuffer();
if(vertexBuffer.isManaged()) {
vertexBuffer.unloadFromActiveBufferObjectManager();
}
}
// ===========================================================
// Methods
// ===========================================================
protected void onInitDraw(final GL10 pGL) {
GLHelper.setColor(pGL, this.mRed, this.mGreen, this.mBlue, this.mAlpha);
GLHelper.enableVertexArray(pGL);
GLHelper.blendFunction(pGL, this.mSourceBlendFunction, this.mDestinationBlendFunction);
}
protected void onApplyVertices(final GL10 pGL) {
if(GLHelper.EXTENSIONS_VERTEXBUFFEROBJECTS) {
final GL11 gl11 = (GL11)pGL;
this.getVertexBuffer().selectOnHardware(gl11);
GLHelper.vertexZeroPointer(gl11);
} else {
GLHelper.vertexPointer(pGL, this.getVertexBuffer().getFloatBuffer());
}
}
protected void updateVertexBuffer() {
this.onUpdateVertexBuffer();
}
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
}