Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 1051 | chris | 1 | package com.gebauz.bauzoid.graphics.sprite; |
| 2 | |||
| 3 | import com.badlogic.gdx.Gdx; |
||
| 4 | import com.badlogic.gdx.graphics.Texture; |
||
| 5 | import com.gebauz.bauzoid.graphics.Graphics; |
||
| 6 | import com.gebauz.bauzoid.graphics.GraphicsObject; |
||
| 7 | import com.gebauz.bauzoid.graphics.model.SimpleGeometry; |
||
| 8 | import com.gebauz.bauzoid.graphics.model.Geometry.PrimitiveType; |
||
| 9 | import com.gebauz.bauzoid.graphics.renderstates.RenderStates; |
||
| 10 | import com.gebauz.bauzoid.graphics.sprite.SpriteRegion; |
||
| 11 | import com.gebauz.bauzoid.graphics.sprite.SpriteShader; |
||
| 12 | import com.gebauz.bauzoid.math.Vector4; |
||
| 13 | |||
| 14 | /** Sprite class that loads a texture and allows definition of regions (for atlasing, or multi-framing). */ |
||
| 15 | public class Sprite extends GraphicsObject |
||
| 16 | { |
||
| 17 | |||
| 18 | // Constants======================================================================================== |
||
| 19 | |||
| 20 | public static int NUM_INDICES_PER_REGION = 6; |
||
| 21 | public static int NUM_ATTRIBUTES_PER_REGION = 4; |
||
| 22 | |||
| 23 | // Embedded Types=================================================================================== |
||
| 24 | |||
| 25 | // Fields=========================================================================================== |
||
| 26 | |||
| 27 | /** The texture this sprite is based on. */ |
||
| 28 | protected Texture mTexture = null; |
||
| 29 | |||
| 30 | /** Stores the separate regions of the sprite that were defined. */ |
||
| 31 | private SpriteRegion[] mRegions = null; |
||
| 32 | |||
| 33 | /** Stores all Geometry of all SpriteRegions. */ |
||
| 34 | private SimpleGeometry mMesh = null; |
||
| 35 | |||
| 36 | /** Store the texture filename so it can be loaded asynchronously later. */ |
||
| 37 | protected String mTextureFilename = null; |
||
| 38 | |||
| 39 | /** Store the atlas region definition filename so it can be loaded asynchronously later. */ |
||
| 40 | protected String mRegionDefFilename = null; |
||
| 41 | |||
| 42 | /** Flag to check if asynchronous or synchronous loading was requested. */ |
||
| 43 | protected boolean mIsAsync = false; |
||
| 44 | |||
| 45 | // Methods========================================================================================== |
||
| 46 | |||
| 47 | public Sprite(Graphics graphics, String textureFile) |
||
| 48 | { |
||
| 49 | super(graphics); |
||
| 50 | mTextureFilename = textureFile; |
||
| 51 | } |
||
| 52 | |||
| 53 | public Sprite(Graphics graphics, String textureFile, String atlasFile) |
||
| 54 | { |
||
| 55 | this(graphics, textureFile); |
||
| 56 | mRegionDefFilename = atlasFile; |
||
| 57 | } |
||
| 58 | |||
| 59 | /** Called during asynchronous loading to initiate AssetManager's loading mechanism. */ |
||
| 60 | public void initAsync() |
||
| 61 | { |
||
| 62 | if (mTextureFilename == null) |
||
| 63 | return; // maybe ASSERT? |
||
| 64 | |||
| 65 | mIsAsync = true; |
||
| 66 | getAssetManager().load(mTextureFilename, Texture.class); |
||
| 67 | |||
| 68 | if (mRegionDefFilename != null) |
||
| 69 | { |
||
| 70 | getAssetManager().load(mRegionDefFilename, SpriteRegionDefinition.class); |
||
| 71 | } |
||
| 72 | } |
||
| 73 | |||
| 74 | /** Called synchronously (or after initAsync() for asynchronous loading). */ |
||
| 75 | public void init() |
||
| 76 | { |
||
| 77 | if (mTextureFilename == null) |
||
| 78 | return; |
||
| 79 | |||
| 80 | if (!mIsAsync) |
||
| 81 | { |
||
| 82 | // load texture synchronously |
||
| 83 | mTexture = new Texture(Gdx.files.internal(mTextureFilename)); |
||
| 84 | } |
||
| 85 | else |
||
| 86 | { |
||
| 87 | // grab texture that should be loaded asynchronously already |
||
| 88 | mTexture = getAssetManager().get(mTextureFilename, Texture.class); |
||
| 89 | } |
||
| 90 | |||
| 91 | if (mRegionDefFilename != null) |
||
| 92 | { |
||
| 93 | SpriteRegionDefinition atlas = null; |
||
| 94 | |||
| 95 | if (!mIsAsync) |
||
| 96 | { |
||
| 97 | // load synchronously |
||
| 98 | atlas = SpriteUtil.readSpriteRegionInfo(Gdx.files.internal(mRegionDefFilename)); |
||
| 99 | } |
||
| 100 | else |
||
| 101 | { |
||
| 102 | atlas = getAssetManager().get(mRegionDefFilename, SpriteRegionDefinition.class); |
||
| 103 | } |
||
| 104 | SpriteRegion regions[] = new SpriteRegion[atlas.frames.size()]; |
||
| 105 | for (int i = 0; i < atlas.frames.size(); i++) |
||
| 106 | { |
||
| 107 | SpriteRegionDefinition.FrameInfo info = atlas.frames.get(i); |
||
| 108 | regions[i] = new SpriteRegion(this, i, info.x, info.y, info.w, info.h, true); |
||
| 109 | } |
||
| 110 | |||
| 111 | setRegions(regions); |
||
| 112 | } |
||
| 113 | else |
||
| 114 | { |
||
| 115 | // create default geometry for entire sprite (make 1 region) |
||
| 116 | SpriteRegion regions[] = new SpriteRegion[1]; |
||
| 117 | regions[0] = new SpriteRegion(this, 0, 0, 0, getTextureWidth(), getTextureHeight(), true); |
||
| 118 | |||
| 119 | setRegions(regions); |
||
| 120 | } |
||
| 121 | } |
||
| 122 | |||
| 123 | /** Destroy sprite. */ |
||
| 124 | public void dispose() |
||
| 125 | { |
||
| 126 | if (mRegions != null) |
||
| 127 | mRegions = null; |
||
| 128 | |||
| 129 | if (mTexture != null) |
||
| 130 | { |
||
| 131 | if (mIsAsync) |
||
| 132 | { |
||
| 133 | getAssetManager().unload(mTextureFilename); |
||
| 134 | } |
||
| 135 | else |
||
| 136 | { |
||
| 137 | mTexture.dispose(); |
||
| 138 | } |
||
| 139 | mTexture = null; |
||
| 140 | } |
||
| 141 | |||
| 142 | if (mRegionDefFilename != null) |
||
| 143 | { |
||
| 144 | if (mIsAsync) |
||
| 145 | { |
||
| 146 | getAssetManager().unload(mRegionDefFilename); |
||
| 147 | } |
||
| 148 | } |
||
| 149 | } |
||
| 150 | |||
| 151 | public void setRegions(SpriteRegion[] regions) |
||
| 152 | { |
||
| 153 | if (mMesh != null) |
||
| 154 | { |
||
| 155 | mMesh.dispose(); |
||
| 156 | mMesh = null; |
||
| 157 | } |
||
| 158 | |||
| 159 | mRegions = regions; |
||
| 160 | mMesh = createGeometry(); |
||
| 161 | } |
||
| 162 | |||
| 163 | public SimpleGeometry createGeometry() |
||
| 164 | { |
||
| 165 | float[] vertices = new float[NUM_ATTRIBUTES_PER_REGION * SimpleGeometry.POSITION_COORD_PER_ELEMENT * mRegions.length]; |
||
| 166 | float[] texCoords = new float[NUM_ATTRIBUTES_PER_REGION * SimpleGeometry.TEXCOORD_COORD_PER_ELEMENT * mRegions.length]; |
||
| 167 | float[] colors = new float[NUM_ATTRIBUTES_PER_REGION * SimpleGeometry.COLOR_COORD_PER_ELEMENT * mRegions.length]; |
||
| 168 | |||
| 169 | // two triangles per region |
||
| 170 | short[] indices = new short[NUM_INDICES_PER_REGION * mRegions.length]; |
||
| 171 | |||
| 172 | for (int i = 0; i < mRegions.length; i++) |
||
| 173 | { |
||
| 174 | SpriteRegion r = getRegion(i); |
||
| 175 | |||
| 176 | float[] v = |
||
| 177 | { |
||
| 178 | -1.0f, -1.0f, 0.0f, |
||
| 179 | 1.0f, -1.0f, 0.0f, |
||
| 180 | 1.0f, 1.0f, 0.0f, |
||
| 181 | -1.0f, 1.0f, 0.0f |
||
| 182 | }; |
||
| 183 | |||
| 184 | float[] t = |
||
| 185 | { |
||
| 186 | r.left, r.top, |
||
| 187 | r.right, r.top, |
||
| 188 | r.right, r.bottom, |
||
| 189 | r.left, r.bottom |
||
| 190 | }; |
||
| 191 | |||
| 192 | float[] c = |
||
| 193 | { |
||
| 194 | 1, 1, 1, 1, |
||
| 195 | 1, 1, 1, 1, |
||
| 196 | 1, 1, 1, 1, |
||
| 197 | 1, 1, 1, 1 |
||
| 198 | }; |
||
| 199 | |||
| 200 | System.arraycopy(v, 0, vertices, NUM_ATTRIBUTES_PER_REGION * SimpleGeometry.POSITION_COORD_PER_ELEMENT * i, v.length); |
||
| 201 | System.arraycopy(t, 0, texCoords, NUM_ATTRIBUTES_PER_REGION * SimpleGeometry.TEXCOORD_COORD_PER_ELEMENT * i, t.length); |
||
| 202 | System.arraycopy(c, 0, colors, NUM_ATTRIBUTES_PER_REGION * SimpleGeometry.COLOR_COORD_PER_ELEMENT * i, c.length); |
||
| 203 | |||
| 204 | int n = i*NUM_INDICES_PER_REGION; |
||
| 205 | short base = (short)(i * NUM_ATTRIBUTES_PER_REGION); |
||
| 206 | indices[n++] = base; indices[n++] = (short)(base+1); indices[n++] = (short)(base+2); |
||
| 207 | indices[n++] = base; indices[n++] = (short)(base+2); indices[n++] = (short)(base+3); |
||
| 208 | } |
||
| 209 | |||
| 210 | |||
| 211 | SimpleGeometry mesh = new SimpleGeometry(getGraphics(), PrimitiveType.TRIANGLES); |
||
| 212 | mesh.setPositions(vertices); |
||
| 213 | mesh.setTexCoords(texCoords); |
||
| 214 | mesh.setColors(colors); |
||
| 215 | mesh.setIndices(indices); |
||
| 216 | |||
| 217 | return mesh; |
||
| 218 | } |
||
| 219 | |||
| 220 | /** Create a single SpriteInstance for a single region. */ |
||
| 221 | public final SpriteInstance createSpriteInstance(int regionIndex) |
||
| 222 | { |
||
| 223 | return new SpriteInstance(getRegion(regionIndex)); |
||
| 224 | } |
||
| 225 | |||
| 226 | /** Create a multiple SpriteInstances, each for a single region. */ |
||
| 227 | public void createSpriteInstances(SpriteInstance[] instances) |
||
| 228 | { |
||
| 229 | if (instances.length < mRegions.length) |
||
| 230 | return; |
||
| 231 | |||
| 232 | for (int i = 0; i < instances.length; i++) |
||
| 233 | { |
||
| 234 | instances[i] = createSpriteInstance(i); |
||
| 235 | } |
||
| 236 | } |
||
| 237 | |||
| 238 | /** Create a multiple SpriteInstances, each for a single region. */ |
||
| 239 | public SpriteInstance[] createSpriteInstances() |
||
| 240 | { |
||
| 241 | SpriteInstance frames[] = new SpriteInstance[mRegions.length]; |
||
| 242 | createSpriteInstances(frames); |
||
| 243 | return frames; |
||
| 244 | } |
||
| 245 | |||
| 246 | /** Create a single SpriteInstance for all regions. */ |
||
| 247 | public SpriteInstance createSpriteInstanceForAll() |
||
| 248 | { |
||
| 249 | SpriteInstance instance = new SpriteInstance(mRegions); |
||
| 250 | return instance; |
||
| 251 | } |
||
| 252 | |||
| 253 | /** Peforms the actual render without any model matrix handling. */ |
||
| 254 | public void performRender(int region, float alpha, Vector4 color) |
||
| 255 | { |
||
| 256 | RenderStates rs = getRenderStates(); |
||
| 257 | SpriteShader shader = getGraphics().getSpriteShader(); |
||
| 258 | |||
| 259 | // draw sprite |
||
| 260 | shader.activate(getTexture(), alpha, color); |
||
| 261 | { |
||
| 262 | rs.blending.setEnabled(true); |
||
| 263 | rs.culling.setEnabled(false); |
||
| 264 | rs.activate(); |
||
| 265 | rs.blending.activate(true); |
||
| 266 | { |
||
| 267 | mMesh.render(getMeshStartIndex(region), NUM_INDICES_PER_REGION); |
||
| 268 | } |
||
| 269 | rs.deactivate(); |
||
| 270 | } |
||
| 271 | shader.deactivate(); |
||
| 272 | } |
||
| 273 | |||
| 274 | // Getters/Setters================================================================================== |
||
| 275 | |||
| 276 | /** Get a reference to the texture. */ |
||
| 277 | public final Texture getTexture() |
||
| 278 | { |
||
| 279 | return mTexture; |
||
| 280 | } |
||
| 281 | |||
| 282 | /** Get the sprite texture's total width. */ |
||
| 283 | public final int getTextureWidth() |
||
| 284 | { |
||
| 285 | if (mTexture == null) |
||
| 286 | return 0; |
||
| 287 | return mTexture.getWidth(); |
||
| 288 | } |
||
| 289 | |||
| 290 | /** Get the sprite texture's total height. */ |
||
| 291 | public final int getTextureHeight() |
||
| 292 | { |
||
| 293 | if (mTexture == null) |
||
| 294 | return 0; |
||
| 295 | return mTexture.getHeight(); |
||
| 296 | } |
||
| 297 | |||
| 298 | /** Get number of defined regions. */ |
||
| 299 | public final int getRegionCount() |
||
| 300 | { |
||
| 301 | if (mRegions == null) |
||
| 302 | return 0; |
||
| 303 | |||
| 304 | return mRegions.length; |
||
| 305 | } |
||
| 306 | |||
| 307 | /** Get region. */ |
||
| 308 | public final SpriteRegion getRegion(int i) |
||
| 309 | { |
||
| 310 | if (mRegions == null) |
||
| 311 | return null; |
||
| 312 | |||
| 313 | return mRegions[i]; |
||
| 314 | } |
||
| 315 | |||
| 316 | /** Get regions array.*/ |
||
| 317 | public final SpriteRegion[] getRegions() |
||
| 318 | { |
||
| 319 | return mRegions; |
||
| 320 | } |
||
| 321 | |||
| 322 | /** Get starting index for region mesh rendering. */ |
||
| 323 | private final int getMeshStartIndex(int regionIndex) |
||
| 324 | { |
||
| 325 | return (regionIndex * NUM_INDICES_PER_REGION); |
||
| 326 | } |
||
| 327 | |||
| 328 | |||
| 329 | |||
| 330 | } |
||
| 331 | |||
| 332 | |||
| 333 |