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
; }
}