package com.arretadogames.pilot.render.opengl;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.RectF;
import android.opengl.GLES11;
import android.opengl.GLUtils;
import android.util.Log;
import android.util.SparseArray;
import com.arretadogames.pilot.MainActivity;
import com.arretadogames.pilot.config.GameSettings;
import com.arretadogames.pilot.loading.FontLoader;
import com.arretadogames.pilot.loading.FontLoader.FontTypeFace;
import com.arretadogames.pilot.loading.FontSpecification;
import com.arretadogames.pilot.loading.ImageLoader;
import com.arretadogames.pilot.loading.LoadableGLObject;
import com.arretadogames.pilot.loading.LoadableType;
import com.arretadogames.pilot.render.PhysicsRect;
import org.jbox2d.common.Vec2;
import java.nio.IntBuffer;
import java.util.HashMap;
import javax.microedition.khronos.opengles.GL10;
public class GLCanvas {
// OpenGLES1.0 Interface
private GL10 gl;
// SparseArray = HashMap<int, GLImage> - DrawableID -> GLImage
private SparseArray<GLTexture> textures = new SparseArray<GLTexture>();
// FontSpecification = Font Properties
private HashMap<FontSpecification, GLTexturedFont> fontTextures = new HashMap<FontSpecification, GLTexturedFont>();
// Rect to be used to store drawing calculations
private Rect auxiliaryRect = new Rect();
// Pixel/Meters Ratio
public static float physicsRatio = 25;
public void setGLInterface(GL10 gl) {
this.gl = gl;
}
public void setPhysicsRatio(float newRatio) {
physicsRatio = newRatio;
}
public boolean initiate() {
GLES11.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// Replace the current matrix with the identity matrix
GLES11.glLoadIdentity();
// Rotate world by 180 around x axis so positive y is down (like canvas)
GLES11.glRotatef(-180, 1, 0, 0);
// Fills the screen with black
setClearColor(255, 0, 0, 0);
return true;
}
public void translate(float dx, float dy) {
GLES11.glTranslatef(dx, dy, 0);
}
public void scale(float sx, float sy, float px, float py) {
GLES11.glTranslatef(px, py, 0);
GLES11.glScalef(sx, sy, 0);
GLES11.glTranslatef(-px, -py, 0);
}
public void rotate(float degrees) {
GLES11.glRotatef(degrees, 0, 0, 1);
}
public void drawDebugRect(int x, int y, int x2, int y2) {
auxiliaryRect.left = x;
auxiliaryRect.top = y;
auxiliaryRect.right = x2;
auxiliaryRect.bottom = y2;
GLRect.draw(gl, x, y, x2, y2, Color.RED);
}
public void saveState() {
GLES11.glPushMatrix();
}
public void restoreState() {
GLES11.glPopMatrix();
}
public void drawText(String text, float x, float y, FontSpecification fs, float size, boolean centered) {
if (fontTextures.get(fs) == null) {
Log.w("GLCanvas", "Font not loaded when drawing (\"" + text + "\")");
if (GameSettings.LAZY_LOAD_ENABLED)
loadFont(fs);
}
fontTextures.get(fs).drawText(gl, text, (int) x, (int) y, size, centered);
}
public void drawText(String text, float x, float y, FontSpecification fs, float size,
boolean centered, float alpha) {
if (alpha >= 0 && alpha <= 255) {
GLES11.glColor4f(1f, 1f, 1f, alpha / 255f);
}
drawText(text, x, y, fs, size, centered);
if (alpha >= 0 && alpha <= 255) {
GLES11.glColor4f(1f, 1f, 1f, 1f);
}
}
private int loadFont(FontSpecification fs) {
GLTexturedFont fontTexture = new GLTexturedFont(fs, gl);
fontTextures.put(fs, fontTexture);
return fontTexture.getGLId();
}
public void setClearColor(float a, float r, float g, float b) {
GLES11.glClearColor(r / 255f, g / 255f, b / 255f, a / 255f);
}
public void drawRect(final RectF dst, int color) {
GLRect.draw(gl, dst.left, dst.top, dst.right, dst.bottom, color);
}
public void drawRect(float left, float top, float right, float bottom, int color) {
GLRect.draw(gl, left, top, right, bottom, color);
}
public void drawLines(Vec2[] vecs, float width, int color, boolean connectStartAndEnd) {
GLLine.drawLineStrip(vecs, vecs.length, width, color, connectStartAndEnd, 1);
}
public void drawPhysicsLines(Vec2[] vecs, int count, float width, int color, boolean connectStartAndEnd) {
GLLine.drawLineStrip(vecs, count, width, color, connectStartAndEnd, GLCanvas.physicsRatio);
}
public void drawPhysicsLines(Vec2[] vecs, int count, float width, int color, boolean connectStartAndEnd, boolean invertY) {
GLLine.drawLineStrip(vecs, count, width, color, connectStartAndEnd, GLCanvas.physicsRatio, invertY, true);
}
public void drawGroundLines(Vec2[] vecs, int count, float width, int color) {
GLLine.drawLineStrip(vecs, count, width, color, false, GLCanvas.physicsRatio, true, false);
}
public void drawBitmap(int imageId, float x, float y, float width, float height) {
drawBitmap(imageId, x, y, width, height, 0, 0, -1);
}
public void drawBitmap(int imageId, float x, float y, float width, float height, float alpha) {
drawBitmap(imageId, x, y, width, height, 0, 0, alpha);
}
public void drawBitmap(int imageId, float x, float y, float width, float height, float extraWidth, float extraHeight) {
drawBitmap(imageId, x, y, width, height, extraWidth, extraHeight, -1);
}
public void drawBitmap(int imageId, float x, float y, float width, float height,
float extraWidth, float extraHeight, float alpha) {
if (textures.get(imageId) == null) {
Log.w("GLCanvas", "Texture not loaded: " +
MainActivity.getContext().getResources().getResourceEntryName(imageId));
if (GameSettings.LAZY_LOAD_ENABLED)
loadImage(imageId);
}
saveState();
if (alpha >= 0 && alpha <= 255) {
GLES11.glColor4f(1f, 1f, 1f, alpha / 255f);
}
translate(x, y);
GLTexture texture = textures.get(imageId);
GLTexturedRect.draw(gl,
0, 0, texture.getTextureWidth() - extraWidth, texture.getTextureHeight() - extraHeight,
0, 0, width, height, texture);
if (alpha >= 0 && alpha <= 255) {
GLES11.glColor4f(1f, 1f, 1f, 1f);
}
restoreState();
}
public void drawBitmap(int imageId, Rect srcRect, RectF dstRect) {
if (textures.get(imageId) == null) {
Log.w("GLCanvas", "Texture not loaded " +
MainActivity.getContext().getResources().getResourceEntryName(imageId));
if (GameSettings.LAZY_LOAD_ENABLED)
loadImage(imageId);
}
GLTexture tex = textures.get(imageId);
auxiliaryRect.left = (int) dstRect.left;
auxiliaryRect.top = (int) dstRect.top;
auxiliaryRect.right = (int) dstRect.right;
auxiliaryRect.bottom = (int) dstRect.bottom;
GLTexturedRect.draw(gl, srcRect, auxiliaryRect, tex);
}
public void drawBitmap(int imageId, RectF dstRect) {
if (textures.get(imageId) == null) {
Log.w("GLCanvas", "Texture not loaded " +
MainActivity.getContext().getResources().getResourceEntryName(imageId));
if (GameSettings.LAZY_LOAD_ENABLED)
loadImage(imageId);
}
GLTexture img = textures.get(imageId);
GLTexturedRect.draw(gl,
0, 0, img.getTextureWidth(), img.getTextureHeight(),
dstRect.left, dstRect.top,
dstRect.right, dstRect.bottom,
textures.get(imageId));
}
public void drawBitmap(int imageId, RectF dstRect, float alpha) {
if (textures.get(imageId) == null) {
Log.w("GLCanvas", "Texture not loaded " +
MainActivity.getContext().getResources().getResourceEntryName(imageId));
if (GameSettings.LAZY_LOAD_ENABLED)
loadImage(imageId);
}
if (alpha >= 0 && alpha <= 255) {
GLES11.glColor4f(1f, 1f, 1f, alpha / 255f);
}
GLTexture img = textures.get(imageId);
GLTexturedRect.draw(gl,
0, 0, img.getTextureWidth(), img.getTextureHeight(),
dstRect.left, dstRect.top,
dstRect.right, dstRect.bottom,
textures.get(imageId));
if (alpha >= 0 && alpha <= 255) {
GLES11.glColor4f(1f, 1f, 1f, 1f);
}
}
public void drawColorRect(int color, PhysicsRect physicsRect) {
GLRect.draw(gl,
physicsRect.left * physicsRatio,
physicsRect.top * physicsRatio,
physicsRect.right * physicsRatio,
physicsRect.bottom * physicsRatio,
color);
}
public void drawBitmap(int imageId, PhysicsRect physicsRect) {
drawBitmap(imageId, physicsRect, 1, 1);
}
public void drawBitmap(int imageId, PhysicsRect physicsRect, float widthRepetitions, float heightRepetitions) {
if (textures.get(imageId) == null) {
Log.w("GLCanvas", "Texture not loaded " +
MainActivity.getContext().getResources().getResourceEntryName(imageId));
if (GameSettings.LAZY_LOAD_ENABLED)
loadImage(imageId);
}
GLTexture tex = textures.get(imageId);
GLTexturedRect.draw(gl,
0f, 0f,
tex.getTextureWidth() * widthRepetitions,
tex.getTextureHeight() * heightRepetitions,
physicsRect.left * physicsRatio,
physicsRect.top * physicsRatio,
physicsRect.right * physicsRatio,
physicsRect.bottom * physicsRatio,
tex);
}
public int loadImage(int imageId) {
// Get bitmap
Bitmap bitmap = ImageLoader.loadImage(imageId);
return loadImage(imageId, bitmap);
}
public void drawRect(
float x, float y,
float x2, float y2,
float x3, float y3,
float x4, float y4,
int colorV1, int colorV2,
int colorV3, int colorV4) {
GLRect.draw(gl,
(x), (y),
(x2),(y2),
(x3), (y3),
(x4), (y4),
colorV1, colorV2, colorV3, colorV4);
}
public void setColor(int color) {
GLES11.glColor4f(Color.red(color) / 255f, Color.green(color) / 255f,
Color.blue(color) / 255f, Color.alpha(color) / 255f);
}
public void resetColor() {
setColor(Color.WHITE);
}
public void drawRectFromPhysics(
float x, float y,
float x2, float y2,
float x3, float y3,
float x4, float y4,
int colorV1, int colorV2,
int colorV3, int colorV4) {
GLRect.draw(gl,
(x*physicsRatio), GameSettings.TARGET_HEIGHT - (y*physicsRatio),
(x2*physicsRatio), GameSettings.TARGET_HEIGHT - (y2*physicsRatio),
(x3*physicsRatio), GameSettings.TARGET_HEIGHT - (y3*physicsRatio),
(x4*physicsRatio), GameSettings.TARGET_HEIGHT - (y4*physicsRatio),
colorV1, colorV2, colorV3, colorV4);
}
private int loadImage(int imageId, Bitmap bitmapToLoad) { /* We also load Bitmaps in FontTexture */
IntBuffer t = IntBuffer.allocate(1);
GLES11.glGenTextures(1, t);
int texture_id = t.get(0);
GLTexture texture = new GLTexture(texture_id);
// Working with textureId
GLES11.glBindTexture(GL10.GL_TEXTURE_2D, texture_id);
// SETTINGS
// Scale up if the texture is smaller.
GLES11.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,
GL10.GL_LINEAR);
// Scale down if the mesh is smaller.
GLES11.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
GL10.GL_LINEAR);
// Clamp to edge behaviour at edge of texture (repeats last pixel)
GLES11.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
GL10.GL_REPEAT);
GLES11.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
GL10.GL_REPEAT);
// Attach bitmap to current texture
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmapToLoad, 0);
// Add dimensional info to spritedata
texture.setDimensions(bitmapToLoad.getWidth(), bitmapToLoad.getHeight());
textures.append(imageId, texture);
return texture_id;
}
public void recycleImage(int imageId) {
// TODO Auto-generated method stub
}
public void translatePhysics(float posX, float posY) {
GLES11.glTranslatef(posX * physicsRatio, GameSettings.TARGET_HEIGHT - posY * physicsRatio, 0);
}
public void removeTextures(LoadableGLObject[] objects) {
int[] glIds = new int[objects.length];
for (int i = 0 ; i < objects.length ; i++) {
if (objects[i].getType().equals(LoadableType.TEXTURE)){
if (textures.get(objects[i].getId()) == null)
continue;
glIds[i] = textures.get(objects[i].getId()).getTextureID();
textures.remove(objects[i].getId());
} else if (objects[i].getType().equals(LoadableType.FONT)) {
// fontTextures.get(key)
}
}
GLES11.glDeleteTextures(glIds.length, glIds, 0);
}
public void loadObject(LoadableGLObject object) {
if (object.getType().equals(LoadableType.TEXTURE)) {
object.setGLId(loadImage(object.getId()));
} else if (object.getType().equals(LoadableType.FONT)) {
object.setGLId(loadFont(FontLoader.getInstance().getFont(FontTypeFace.values()[object.getId()])));
}
}
private Vec2[] auxVec = new Vec2[] { new Vec2(), new Vec2() };
public void drawLine(float f, float g, float h, float i, float width, int color) {
auxVec[0].x = f;
auxVec[0].y = g;
auxVec[1].x = h;
auxVec[1].y = i;
drawLines(auxVec, width, color, false);
}
}