[added] Ability to redefine a cache with SpriteCache.
Gdx.files.classpath("com/badlogic/gdx/utils/arial-15.png"), false);\r
}\r
\r
- public BitmapFont(FileHandle fontFile, Sprite sprite) {\r
- init(fontFile, sprite, false);\r
+ /**\r
+ * Creates a new BitmapFont with the glyphs relative to the specified sprite.\r
+ * @param sprite The sprite containing the glyphs. It must NOT be flipped.\r
+ * @param flip If true, the glyphs will be flipped for use with a perspective where 0,0 is the upper left corner.\r
+ */\r
+ public BitmapFont(FileHandle fontFile, Sprite sprite, boolean flip) {\r
+ init(fontFile, sprite, flip);\r
}\r
\r
/**\r
\r
private void init(FileHandle fontFile, Sprite sprite, boolean flip) {\r
this.sprite = sprite;\r
- float invTexWidth = 1.0f / sprite.getWidth();\r
- float invTexHeight = 1.0f / sprite.getHeight();\r
+ float invTexWidth = 1.0f / sprite.getTexture().getWidth();\r
+ float invTexHeight = 1.0f / sprite.getTexture().getHeight();\r
float uSprite = sprite.getTextureRegionX();\r
float vSprite = sprite.getTextureRegionY();\r
float u2Sprite = uSprite + sprite.getTextureRegionWidth();\r
glyph.u = uSprite + srcX * invTexWidth;\r
glyph.u2 = uSprite + (srcX + glyph.width) * invTexWidth;\r
if (flip) {\r
- glyph.v = srcY * invTexHeight;\r
- glyph.v2 = (srcY + glyph.height) * invTexHeight;\r
+ glyph.v = vSprite + srcY * invTexHeight;\r
+ glyph.v2 = vSprite + (srcY + glyph.height) * invTexHeight;\r
} else {\r
- glyph.v2 = srcY * invTexHeight;\r
- glyph.v = (srcY + glyph.height) * invTexHeight;\r
+ glyph.v2 = vSprite + srcY * invTexHeight;\r
+ glyph.v = vSprite + (srcY + glyph.height) * invTexHeight;\r
}\r
}\r
\r
spriteBatch.draw(texture, getVertices(), 0, 20);\r
}\r
\r
+ /**\r
+ * Sets the sprite's texture. The texture region is unaffected.\r
+ */\r
public void setTexture(Texture texture) {\r
this.texture = texture;\r
}\r
}\r
\r
public float getTextureRegionY () {\r
- return vertices[V1];\r
+ return vertices[V2];\r
}\r
\r
public float getTextureRegionWidth () {\r
}\r
\r
public float getTextureRegionHeight () {\r
- return vertices[V1] - vertices[V2];\r
+ return vertices[V2] - vertices[V1];\r
}\r
\r
/**\r
\r
package com.badlogic.gdx.graphics;\r
\r
+import java.nio.FloatBuffer;\r
import java.util.ArrayList;\r
\r
import com.badlogic.gdx.ApplicationListener;\r
import com.badlogic.gdx.graphics.VertexAttributes.Usage;\r
import com.badlogic.gdx.graphics.glutils.ShaderProgram;\r
import com.badlogic.gdx.math.Matrix4;\r
+import com.badlogic.gdx.utils.GdxRuntimeException;\r
import com.badlogic.gdx.utils.MathUtils;\r
\r
/**\r
private final Matrix4 combinedMatrix = new Matrix4();\r
private ShaderProgram shader;\r
\r
- private boolean caching;\r
+ private Cache currentCache;\r
private final ArrayList<Texture> textures = new ArrayList(8);\r
private final ArrayList<Integer> counts = new ArrayList(8);\r
- private int offset;\r
\r
/**\r
* Creates a cache that can contain up to 1000 images.\r
* Starts the definition of a new cache, allowing the add and {@link #endCache()} methods to be called.\r
*/\r
public void beginCache () {\r
- if (caching) throw new IllegalStateException("endCache must be called before begin.");\r
- caching = true;\r
-\r
- offset = mesh.getNumVertices() / 2 * 6;\r
+ if (currentCache != null) throw new IllegalStateException("endCache must be called before begin.");\r
+ currentCache = new Cache(caches.size(), mesh.getNumVertices() / 2 * 6);\r
+ caches.add(currentCache);\r
mesh.getVerticesBuffer().compact();\r
}\r
\r
/**\r
+ * Starts the redefinition of an existing cache, allowing the add and {@link #endCache()} methods to be called. The cache\r
+ * cannot have more entries added to it than when it was first created.\r
+ */\r
+ public void beginCache (int cacheID) {\r
+ if (currentCache != null) throw new IllegalStateException("endCache must be called before begin.");\r
+ currentCache = caches.get(cacheID);\r
+ mesh.getVerticesBuffer().position(currentCache.offset);\r
+ }\r
+\r
+ /**\r
* Ends the definition of a cache, returning the cache ID to be used with {@link #draw(int)}.\r
*/\r
public int endCache () {\r
- if (!caching) throw new IllegalStateException("beginCache must be called before endCache.");\r
- caching = false;\r
-\r
- Cache cache = new Cache(offset, textures.toArray(new Texture[textures.size()]), new int[counts.size()]);\r
- for (int i = 0, n = counts.size(); i < n; i++)\r
- cache.counts[i] = counts.get(i);\r
- caches.add(cache);\r
-\r
- mesh.getVerticesBuffer().flip();\r
+ if (currentCache == null) throw new IllegalStateException("beginCache must be called before endCache.");\r
+\r
+ Cache cache = currentCache;\r
+ int cacheCount = mesh.getVerticesBuffer().position() - cache.offset;\r
+ if (cache.textures == null) {\r
+ // New cache.\r
+ cache.maxCount = cacheCount;\r
+ cache.textures = textures.toArray(new Texture[textures.size()]);\r
+ cache.counts = new int[counts.size()];\r
+ for (int i = 0, n = counts.size(); i < n; i++)\r
+ cache.counts[i] = counts.get(i);\r
+\r
+ mesh.getVerticesBuffer().flip();\r
+ } else {\r
+ // Redefine existing cache.\r
+ if (cacheCount > cache.maxCount)\r
+ throw new GdxRuntimeException("Cannot redefine a cache with more entries than when it was first created: "\r
+ + cacheCount + " (" + cache.maxCount + " max)");\r
+\r
+ if (cache.textures.length < textures.size()) cache.textures = new Texture[textures.size()];\r
+ for (int i = 0, n = textures.size(); i < n; i++)\r
+ cache.textures[i] = textures.get(i);\r
+\r
+ if (cache.counts.length < counts.size()) cache.counts = new int[counts.size()];\r
+ for (int i = 0, n = counts.size(); i < n; i++)\r
+ cache.counts[i] = counts.get(i);\r
+\r
+ FloatBuffer vertices = mesh.getVerticesBuffer();\r
+ vertices.position(0);\r
+ Cache lastCache = caches.get(caches.size() - 1);\r
+ vertices.limit(lastCache.offset + lastCache.maxCount);\r
+ }\r
\r
+ currentCache = null;\r
textures.clear();\r
counts.clear();\r
\r
* Adds the specified image to the cache.\r
*/\r
public void add (Texture texture, float[] vertices, int offset, int length) {\r
- if (!caching) throw new IllegalStateException("beginCache must be called before add.");\r
+ if (currentCache == null) throw new IllegalStateException("beginCache must be called before add.");\r
\r
int count = vertices.length / Sprite.SPRITE_SIZE * 6;\r
int lastIndex = textures.size() - 1;\r
}\r
\r
static private class Cache {\r
+ final int id;\r
final int offset;\r
- final Texture[] textures;\r
- final int[] counts;\r
+ int maxCount;\r
+ Texture[] textures;\r
+ int[] counts;\r
\r
- Cache (int offset, Texture[] textures, int[] counts) {\r
+ public Cache (int id, int offset) {\r
+ this.id = id;\r
this.offset = offset;\r
- this.textures = textures;\r
- this.counts = counts;\r
}\r
}\r
\r
return super.getY() - offsetY;\r
}\r
\r
- // BOZO - Test flip works.\r
public void flip (boolean x, boolean y) {\r
super.flip(x, y);\r
if (x) {\r
return index;\r
}\r
\r
+ /**\r
+ * The width of the image, before whitespace was removed for packing.\r
+ */\r
public int getOriginalWidth () {\r
return originalWidth;\r
}\r
\r
+ /**\r
+ * The height of the image, before whitespace was removed for packing.\r
+ */\r
public int getOriginalHeight () {\r
return originalHeight;\r
}\r
\r
/**\r
- * The offset from the left of the original image to the left of the packed image, after whitespace has been removed.\r
+ * The offset from the left of the original image to the left of the packed image, after whitespace was removed for packing.\r
*/\r
public int getOffsetX () {\r
return offsetX;\r
}\r
\r
/**\r
- * The offset from the bottom of the original image to the bottom of the packed image, after whitespace has been removed.\r
+ * The offset from the bottom of the original image to the bottom of the packed image, after whitespace was removed for\r
+ * packing.\r
*/\r
public int getOffsetY () {\r
return offsetY;\r
\r
import com.badlogic.gdx.Files.FileType;\r
import com.badlogic.gdx.Gdx;\r
+import com.badlogic.gdx.Input;\r
import com.badlogic.gdx.InputProcessor;\r
import com.badlogic.gdx.graphics.Color;\r
import com.badlogic.gdx.graphics.GL10;\r
import com.badlogic.gdx.graphics.Texture.TextureFilter;\r
import com.badlogic.gdx.graphics.Texture.TextureWrap;\r
import com.badlogic.gdx.tests.utils.GdxTest;\r
+import com.badlogic.gdx.utils.MathUtils;\r
\r
public class SpriteCacheTest extends GdxTest implements InputProcessor {\r
int SPRITES = 400 / 2;\r
int normalCacheID, spriteCacheID;\r
int renderMethod = 0;\r
\r
+ private float[] sprites;\r
+\r
+ private float[] sprites2;\r
+\r
@Override public void render () {\r
if (renderMethod == 0) renderNormal();\r
;\r
TextureWrap.ClampToEdge);\r
pixmap.dispose();\r
\r
- float sprites[] = new float[SPRITES * 6];\r
- float sprites2[] = new float[SPRITES * 6];\r
+ sprites = new float[SPRITES * 6];\r
+ sprites2 = new float[SPRITES * 6];\r
Sprite[] sprites3 = new Sprite[SPRITES * 2];\r
\r
for (int i = 0; i < sprites.length; i += 6) {\r
}\r
\r
@Override public boolean keyDown (int keycode) {\r
+ if (keycode != Input.Keys.KEYCODE_SPACE) return false;\r
+ float scale = MathUtils.random(0.75f, 1.25f);\r
+ float angle = MathUtils.random(1, 360);\r
+ spriteCache.beginCache(normalCacheID);\r
+ for (int i = 0; i < sprites2.length; i += 6)\r
+ spriteCache.add(texture2, sprites2[i], sprites2[i + 1], 16, 16, 32, 32, scale, scale, angle, 0, 0, 32, 32, Color.WHITE,\r
+ false, false);\r
+ for (int i = 0; i < sprites.length; i += 6)\r
+ spriteCache.add(texture, sprites[i], sprites[i + 1], 16, 16, 32, 32, scale, scale, angle, 0, 0, 32, 32, Color.WHITE,\r
+ false, false);\r
+ spriteCache.endCache();\r
return false;\r
}\r
\r