Subversion Repositories AndroidProjects

Rev

Blame | Last modification | View Log | RSS feed

package com.gebauz.bauzoid.graphics.sprite;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.gebauz.bauzoid.graphics.Graphics;
import com.gebauz.bauzoid.graphics.GraphicsObject;
import com.gebauz.bauzoid.graphics.model.SimpleGeometry;
import com.gebauz.bauzoid.graphics.model.Geometry.PrimitiveType;
import com.gebauz.bauzoid.graphics.renderstates.RenderStates;
import com.gebauz.bauzoid.graphics.sprite.SpriteRegion;
import com.gebauz.bauzoid.graphics.sprite.SpriteShader;
import com.gebauz.bauzoid.math.Vector4;

/** Sprite class that loads a texture and allows definition of regions (for atlasing, or multi-framing). */
public class Sprite extends GraphicsObject
{

        // Constants========================================================================================
       
        public static int NUM_INDICES_PER_REGION = 6;
        public static int NUM_ATTRIBUTES_PER_REGION = 4;

        // Embedded Types===================================================================================

        // Fields===========================================================================================
       
        /** The texture this sprite is based on. */
        protected Texture mTexture = null;
       
        /** Stores the separate regions of the sprite that were defined. */
        private SpriteRegion[] mRegions = null;
       
        /** Stores all Geometry of all SpriteRegions. */
        private SimpleGeometry mMesh = null;
       
        /** Store the texture filename so it can be loaded asynchronously later. */
        protected String mTextureFilename = null;
       
        /** Store the atlas region definition filename so it can be loaded asynchronously later. */
        protected String mRegionDefFilename = null;
       
        /** Flag to check if asynchronous or synchronous loading was requested. */
        protected boolean mIsAsync = false;
       
        // Methods==========================================================================================
       
        public Sprite(Graphics graphics, String textureFile)
        {
                super(graphics);
                mTextureFilename = textureFile;
        }
       
        public Sprite(Graphics graphics, String textureFile, String atlasFile)
        {
                this(graphics, textureFile);
                mRegionDefFilename = atlasFile;
        }
       
        /** Called during asynchronous loading to initiate AssetManager's loading mechanism. */
        public void initAsync()
        {
                if (mTextureFilename == null)
                        return; // maybe ASSERT?
               
                mIsAsync = true;
                getAssetManager().load(mTextureFilename, Texture.class);
               
                if (mRegionDefFilename != null)
                {
                        getAssetManager().load(mRegionDefFilename, SpriteRegionDefinition.class);
                }
        }
       
        /** Called synchronously (or after initAsync() for asynchronous loading). */
        public void init()
        {
                if (mTextureFilename == null)
                        return;
               
                if (!mIsAsync)
                {
                        // load texture synchronously
                        mTexture = new Texture(Gdx.files.internal(mTextureFilename));
                }
                else
                {
                        // grab texture that should be loaded asynchronously already
                        mTexture = getAssetManager().get(mTextureFilename, Texture.class);
                }

                if (mRegionDefFilename != null)
                {
                        SpriteRegionDefinition atlas = null;
                       
                        if (!mIsAsync)
                        {
                                // load synchronously
                                atlas = SpriteUtil.readSpriteRegionInfo(Gdx.files.internal(mRegionDefFilename));
                        }
                        else
                        {
                                atlas = getAssetManager().get(mRegionDefFilename, SpriteRegionDefinition.class);
                        }
                        SpriteRegion regions[] = new SpriteRegion[atlas.frames.size()];
                        for (int i = 0; i < atlas.frames.size(); i++)
                        {
                                SpriteRegionDefinition.FrameInfo info = atlas.frames.get(i);
                                regions[i] = new SpriteRegion(this, i, info.x, info.y, info.w, info.h, true);
                        }

                        setRegions(regions);
                }
                else
                {
                        // create default geometry for entire sprite (make 1 region)
                        SpriteRegion regions[] = new SpriteRegion[1];
                        regions[0] = new SpriteRegion(this, 0, 0, 0, getTextureWidth(), getTextureHeight(), true);
                       
                        setRegions(regions);
                }
        }
       
        /** Destroy sprite. */
        public void dispose()
        {
                if (mRegions != null)
                        mRegions = null;
               
                if (mTexture != null)
                {
                        if (mIsAsync)
                        {
                                getAssetManager().unload(mTextureFilename);
                        }
                        else
                        {
                                mTexture.dispose();
                        }
                        mTexture = null;
                }
               
                if (mRegionDefFilename != null)
                {
                        if (mIsAsync)
                        {
                                getAssetManager().unload(mRegionDefFilename);
                        }
                }
        }
       
        public void setRegions(SpriteRegion[] regions)
        {
                if (mMesh != null)
                {
                        mMesh.dispose();
                        mMesh = null;
                }
               
                mRegions = regions;
                mMesh = createGeometry();      
        }
       
        public SimpleGeometry createGeometry()
        {
                float[] vertices = new float[NUM_ATTRIBUTES_PER_REGION * SimpleGeometry.POSITION_COORD_PER_ELEMENT * mRegions.length];
                float[] texCoords = new float[NUM_ATTRIBUTES_PER_REGION * SimpleGeometry.TEXCOORD_COORD_PER_ELEMENT * mRegions.length];
                float[] colors = new float[NUM_ATTRIBUTES_PER_REGION * SimpleGeometry.COLOR_COORD_PER_ELEMENT * mRegions.length];
               
                // two triangles per region
                short[] indices = new short[NUM_INDICES_PER_REGION * mRegions.length];
               
                for (int i = 0; i < mRegions.length; i++)
                {
                        SpriteRegion r = getRegion(i);
                       
                        float[] v =
                        {
                                -1.0f, -1.0f, 0.0f,
                                 1.0f, -1.0f, 0.0f,
                                 1.0f,  1.0f, 0.0f,
                                -1.0f,  1.0f, 0.0f
                        };
                       
                        float[] t =
                        {
                                r.left, r.top,
                                r.right, r.top,
                                r.right, r.bottom,
                                r.left, r.bottom
                        };
                       
                        float[] c =
                        {
                                1, 1, 1, 1,
                                1, 1, 1, 1,
                                1, 1, 1, 1,
                                1, 1, 1, 1
                        };
                       
                        System.arraycopy(v, 0, vertices, NUM_ATTRIBUTES_PER_REGION * SimpleGeometry.POSITION_COORD_PER_ELEMENT * i, v.length);
                        System.arraycopy(t, 0, texCoords, NUM_ATTRIBUTES_PER_REGION * SimpleGeometry.TEXCOORD_COORD_PER_ELEMENT * i, t.length);
                        System.arraycopy(c, 0, colors, NUM_ATTRIBUTES_PER_REGION * SimpleGeometry.COLOR_COORD_PER_ELEMENT * i, c.length);
                       
                        int n = i*NUM_INDICES_PER_REGION;                      
                        short base = (short)(i * NUM_ATTRIBUTES_PER_REGION);
                        indices[n++] = base; indices[n++] = (short)(base+1); indices[n++] = (short)(base+2);
                        indices[n++] = base; indices[n++] = (short)(base+2); indices[n++] = (short)(base+3);
                }
               
               
                SimpleGeometry mesh = new SimpleGeometry(getGraphics(), PrimitiveType.TRIANGLES);
                mesh.setPositions(vertices);
                mesh.setTexCoords(texCoords);
                mesh.setColors(colors);
                mesh.setIndices(indices);
               
                return mesh;
        }
       
        /** Create a single SpriteInstance for a single region. */
        public final SpriteInstance createSpriteInstance(int regionIndex)
        {
                return new SpriteInstance(getRegion(regionIndex));
        }
       
        /** Create a multiple SpriteInstances, each for a single region. */
        public void createSpriteInstances(SpriteInstance[] instances)
        {
                if (instances.length < mRegions.length)
                        return;
               
                for (int i = 0; i < instances.length; i++)
                {
                        instances[i] = createSpriteInstance(i);
                }
        }
       
        /** Create a multiple SpriteInstances, each for a single region. */
        public SpriteInstance[] createSpriteInstances()
        {
                SpriteInstance frames[] = new SpriteInstance[mRegions.length];
                createSpriteInstances(frames);
                return frames;
        }
       
        /** Create a single SpriteInstance for all regions. */
        public SpriteInstance createSpriteInstanceForAll()
        {
                SpriteInstance instance = new SpriteInstance(mRegions);
                return instance;
        }
       
        /** Peforms the actual render without any model matrix handling. */
        public void performRender(int region, float alpha, Vector4 color)
        {
                RenderStates rs = getRenderStates();
                SpriteShader shader = getGraphics().getSpriteShader();

                // draw sprite
                shader.activate(getTexture(), alpha, color);
                {
                        rs.blending.setEnabled(true);                  
                        rs.culling.setEnabled(false);
                        rs.activate();
                        rs.blending.activate(true);
                        {
                                mMesh.render(getMeshStartIndex(region), NUM_INDICES_PER_REGION);
                        }
                        rs.deactivate();
                }
                shader.deactivate();
        }

        // Getters/Setters==================================================================================

        /** Get a reference to the texture. */
        public final Texture getTexture()
        {
                return mTexture;
        }
       
        /** Get the sprite texture's total width. */
        public final int getTextureWidth()
        {
                if (mTexture == null)
                        return 0;
                return mTexture.getWidth();
        }
       
        /** Get the sprite texture's total height. */
        public final int getTextureHeight()
        {
                if (mTexture == null)
                        return 0;
                return mTexture.getHeight();
        }
       
        /** Get number of defined regions. */
        public final int getRegionCount()
        {
                if (mRegions == null)
                        return 0;
               
                return mRegions.length;
        }
       
        /** Get region. */
        public final SpriteRegion getRegion(int i)
        {
                if (mRegions == null)
                        return null;
               
                return mRegions[i];
        }
       
        /** Get regions array.*/
        public final SpriteRegion[] getRegions()
        {
                return mRegions;
        }
       
        /** Get starting index for region mesh rendering. */
        private final int getMeshStartIndex(int regionIndex)
        {
                return (regionIndex * NUM_INDICES_PER_REGION);
        }
       
       
       
}