Subversion Repositories AndroidProjects

Rev

Rev 537 | Go to most recent revision | Blame | Compare with Previous | 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.Geometry.PrimitiveType;
import com.gebauz.Bauzoid.graphics.model.SimpleGeometry;
import com.gebauz.Bauzoid.graphics.renderstates.RenderStates;
import com.gebauz.Bauzoid.math.Matrix4;
import com.gebauz.Bauzoid.math.Vector2;
import com.gebauz.Bauzoid.math.Vector4;

/** Sprite class.
 * Implements a 2D sprite that renders from a portion of a
 * texture to a quad onscreen.
 *
 * The class is capable of
 * - Rotation and scale transformation via pivot point
 * - Fading (done through shader instead of setting vertex colors)
 *
 * For using multiple texture regions as frames,
 * use @link AtlasSprite.
 */

public class Sprite extends GraphicsObject
{
        public float x = 0.0f;
        public float y = 0.0f;
        public float w = 0.0f;
        public float h = 0.0f;
        public float angle = 0.0f;
        public float alpha = 1.0f;
        public Vector4 color = new Vector4(1.0f, 1.0f, 1.0f, 1.0f);
       
        public boolean mirrorX = false;
        public boolean mirrorY = false;
       
        /** Rotation and scaling pivot point in absolute coordinates. */
        public float pivotX = 0.0f;
        public float pivotY = 0.0f;
       
        protected Texture mTexture = null;
        protected SimpleGeometry mMesh = null;
       
        private Matrix4 mScale = new Matrix4();
        private Matrix4 mMirror = new Matrix4();
        private Matrix4 mPivotTranslate = new Matrix4();
        private Matrix4 mRotateZ = new Matrix4();
        private Matrix4 mTranslate = new Matrix4();
       
        private Matrix4 mModelMatrix = new Matrix4();
       
        protected String mFilename = null;
        protected boolean mIsAsync = false;
       
        /** Constructor. Does not load anything yet
         */
   
        public Sprite(Graphics graphics, String filename)
        {
                super(graphics);
                mFilename = filename;
        }
       
        /** Called during asynchronous loading - initiates texture loading. */
        public void initAsync()
        {
                if (mFilename == null)
                        return;
               
                mIsAsync = true;
                getAssetManager().load(mFilename, Texture.class);
        }
       
        /** Called synchronously after initAsync() has been called. */
        public void init(float _x, float _y, float _w, float _h, float _pivotX, float _pivotY)
        {
                if (mFilename == null)
                        return;
               
                if (!mIsAsync)
                {
                        // load texture synchronously
                        mTexture = new Texture(Gdx.files.internal(mFilename));
                }
                else
                {
                        // grab texture that should be loaded asynchronously already
                        mTexture = getAssetManager().get(mFilename, Texture.class);
                }
               
                w = _w;
                h = _h;
                pivotX = _pivotX;
                pivotY = _pivotY;

                initGeometry();
        }
       
        public void init(float _x, float _y, float _w, float _h)
        {
                init(_x, _y, _w, _h, _w/2, _h/2);
        }
       
        public void init()
        {
                init(0, 0, 0, 0);
               
                if (mTexture != null)
                {
                        w = mTexture.getWidth();
                        h = mTexture.getHeight();
                        pivotX = w/2;
                        pivotY = h/2;
                }
        }
       
        protected void initGeometry()
        {
                float[] vertices = {
                        0.0f, 0.0f, 0.0f,
                        1.0f, 0.0f, 0.0f,
                        1.0f, 1.0f, 0.0f,
                        0.0f, 1.0f, 0.0f
                };

                float[] texCoords = {
                        0.0f, 0.0f,
                        1.0f, 0.0f,
                        1.0f, 1.0f,
                        0.0f, 1.0f
                };
               
                float[] colors = {
                        1, 1, 1, 1,
                        1, 1, 1, 1,
                        1, 1, 1, 1,
                        1, 1, 1, 1
                };
               
                short[] indices = {
                        0, 1, 2,
                        0, 2, 3
                };
               
                mMesh = new SimpleGeometry(getGraphics(), PrimitiveType.TRIANGLES);
                mMesh.setPositions(vertices);
                mMesh.setTexCoords(texCoords, false);
                mMesh.setColors(colors);
                mMesh.setIndices(indices);             
        }
       
        public void dispose()
        {
                if (mTexture != null)
                {
                        if (mIsAsync)
                        {
                                getAssetManager().unload(mFilename);
                        }
                        else
                        {
                                mTexture.dispose();
                        }
                        mTexture = null;
                }
        }
       
        public void update(float deltaTime)
        {
               
        }
       
        public void render()
        {
                render(x, y, w, h);
        }
       
        public void render(float _x, float _y, float _w, float _h)
        {
                SpriteShader shader = getGraphics().getSpriteShader();
                RenderStates rs = getRenderStates();
               
                mScale.setScale(_w, _h, 1.0f);
                mPivotTranslate.setTranslation(-pivotX, -pivotY, 0);
                mMirror.setScale((mirrorX ? -1 : 1), (mirrorY ? -1 : 1), 1);
                mRotateZ.setRotationZ(angle);
                mTranslate.setTranslation(_x, _y, 0);
                mModelMatrix.identity();
               
                Matrix4.multiply(mModelMatrix, mScale, mPivotTranslate);
                Matrix4.multiply(mModelMatrix, mModelMatrix, mMirror);
                Matrix4.multiply(mModelMatrix, mModelMatrix, mRotateZ);
                Matrix4.multiply(mModelMatrix, mModelMatrix, mTranslate);
               
                rs.pushModelMatrix();
                {
                        rs.model = mModelMatrix;
                       
                        // draw sprite
                        shader.activate(mTexture, alpha, color);
                        {
                                rs.blending.setEnabled(true);
                                rs.culling.setEnabled(false);
                                rs.activate();
                                {
                                        mMesh.render();
                                }
                                rs.deactivate();
                        }
                        shader.deactivate();
                }
                rs.popModelMatrix();
        }
       
        /** Center the pivot. */
        public void centerPivot()
        {
                pivotX = w/2.0f;
                pivotY = h/2.0f;
        }

        /** 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 a reference to the texture. */
        public final Texture getTexture()
        {
                return mTexture;
        }
       
        /** Set a new texture, with the old one (if any) getting destroyed. */
        public final void setTexture(Texture texture)
        {
                if (mTexture != null)
                        mTexture.dispose();
               
                mTexture = texture;
        }
       
        /** Get the upper left corner as a Vector2. */
        public Vector2 getTopLeft()
        {
                return new Vector2(x - pivotX, y - pivotY);
        }
       
        /** Get the upper left corner as a Vector2. */
        public Vector2 getTopRight()
        {
                return new Vector2(x - pivotX + w, y - pivotY);
        }
       
        /** Get the upper left corner as a Vector2. */
        public Vector2 getBottomLeft()
        {
                return new Vector2(x - pivotX, y - pivotY + h);
        }
       
        /** Get the upper left corner as a Vector2. */
        public Vector2 getBottomRight()
        {
                return new Vector2(x - pivotX + w, y - pivotY + h);
        }
       
        /** Check if the point is inside the sprite. */
        public boolean isInside(float x, float y)
        {
                Vector2 topLeft = getTopLeft();
                Vector2 bottomRight = getBottomRight();
               
                return ( (x >= topLeft.x) && (y >= topLeft.y) &&
                                 (x <= bottomRight.x) && (y <= bottomRight.y) );
        }
       
        /** Check if the Sprite has been asynchronously loaded. */
        public final boolean isAsync() { return mIsAsync; }
}