Subversion Repositories AndroidProjects

Rev

Blame | Last modification | View Log | RSS feed

package com.gebauz.bauzoid.graphics.spritex;

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.graphics.sprite.SpriteShader;
import com.gebauz.bauzoid.math.Matrix4;
import com.gebauz.bauzoid.math.Vector2;

/** 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 SpriteParameters param = new SpriteParameters();
       
        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);
                }
               
                param.x = _x;
                param.y = _y;          
                param.w = _w;
                param.h = _h;
                param.pivotX = _pivotX;
                param.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)
                {
                        param.w = mTexture.getWidth();
                        param.h = mTexture.getHeight();
                        param.pivotX = param.w/2;
                        param.pivotY = param.h/2;
                }
        }
       
        protected void initGeometry()
        {
                float[] vertices = {
                        -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[] 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(param.x, param.y, param.w, param.h);
        }
       
        public void render(float _x, float _y, float _w, float _h)
        {
                render(_x, _y, _w, _h, param.pivotX, param.pivotY, param.angle, param.mirrorX, param.mirrorY);
        }
       
        public void render(float _x, float _y, float _w, float _h, float _pivotX, float _pivotY)
        {
                render(_x, _y, _w, _h, _pivotX, _pivotY, param.angle, param.mirrorX, param.mirrorY);
        }
       
        public void render(float _x, float _y, float _w, float _h, float _pivotX, float _pivotY, float _angle)
        {
                render(_x, _y, _w, _h, _pivotX, _pivotY, _angle, param.mirrorX, param.mirrorY);
        }
       
        public void render(float _x, float _y, float _w, float _h, float _pivotX, float _pivotY, float _angle, boolean _mirrorX, boolean _mirrorY)
        {
                SpriteShader shader = getGraphics().getSpriteShader();
                RenderStates rs = getRenderStates();
               
/*              mScale.setScale(_w, _h, 1.0f);
                mPivotTranslate.setTranslation(-param.pivotX, -param.pivotY, 0);
                mMirror.setScale((param.mirrorX ? -1 : 1), (param.mirrorY ? -1 : 1), 1);
                mRotateZ.setRotationZ(param.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);*/

               
                mScale.setScale(_w/2, _h/2, 1.0f);
                mPivotTranslate.setTranslation(-_pivotX+_w/2, -_pivotY+_h/2, 0);
                mMirror.setScale((_mirrorX ? -1 : 1), (_mirrorY ? -1 : 1), 1);
                mRotateZ.setRotationZ(_angle);
                mTranslate.setTranslation(_x, _y, 0);

                mModelMatrix.identity();
               
                Matrix4.multiply(mModelMatrix, mModelMatrix, mMirror);
               
                Matrix4.multiply(mModelMatrix, mModelMatrix, mScale);
                               
                Matrix4.multiply(mModelMatrix,  mModelMatrix, mPivotTranslate);

                Matrix4.multiply(mModelMatrix, mModelMatrix, mRotateZ);

                Matrix4.multiply(mModelMatrix, mModelMatrix, mTranslate);
               
                rs.pushModelMatrix();
                {
                        rs.model = mModelMatrix;
                       
                        // draw sprite
                        shader.activate(mTexture, param.alpha, param.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()
        {
                param.pivotX = param.w/2.0f;
                param.pivotY = param.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 param.getTopLeft();
        }
       
        /** Get the upper left corner as a Vector2. */
        public Vector2 getTopRight()
        {
                return param.getTopRight();
        }
       
        /** Get the upper left corner as a Vector2. */
        public Vector2 getBottomLeft()
        {
                return param.getBottomLeft();
        }
       
        /** Get the upper left corner as a Vector2. */
        public Vector2 getBottomRight()
        {
                return param.getBottomRight();
        }
       
        /** Check if the point is inside the sprite. */
        public boolean isInside(float x, float y)
        {
                return isInside(x, y);
        }
       
        /** Check if the Sprite has been asynchronously loaded. */
        public final boolean isAsync() { return mIsAsync; }
}