package com.gebauz.bauzoid2.graphics.sprite;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.gebauz.bauzoid2.game.Engine;
import com.gebauz.bauzoid2.graphics.geometry.Geometry;
import com.gebauz.bauzoid2.graphics.geometry.SimpleGeometry;
import com.gebauz.bauzoid2.math.MathUtil;
import com.gebauz.bauzoid2.math.Vector4;
import com.gebauz.bauzoid2.util.IAsyncLoadable;
public class SpriteSheet
implements IAsyncLoadable
{
// Constants========================================================================================
public static final int NUM_INDICES_PER_REGION =
6;
public static final int NUM_ATTRIBUTES_PER_REGION =
4;
// Embedded Types===================================================================================
// Fields===========================================================================================
private String mTextureFile =
null;
private String mSheetFile =
null;
private Texture mTexture =
null;
private SimpleGeometry mGeometry =
null;
private SpriteSheetRegion
[] mRegions =
null;
private IAsyncLoadable.
Tracker mAsync =
new IAsyncLoadable.
Tracker();
// Methods==========================================================================================
public SpriteSheet
(String textureFile
)
{
mTextureFile = textureFile
;
}
public SpriteSheet
(String textureFile,
String sheetFile
)
{
mTextureFile = textureFile
;
mSheetFile = sheetFile
;
}
public SpriteSheet
(String textureFile, SpriteSheetRegion
[] regions
)
{
this(textureFile
);
mRegions = regions
;
}
public void initAsync
()
{
if (mTextureFile ==
null)
{
// need at least a texture file
Engine.
logError("No texture file specified in Sprite");
return;
}
mAsync.
setAsync();
Engine.
assets.
load(mTextureFile, Texture.
class);
if (mSheetFile
!=
null)
{
Engine.
assets.
load(mSheetFile, SpriteSheetDefinition.
class);
}
}
public void init
()
{
if (mTextureFile ==
null)
return;
SpriteSheetDefinition def =
null;
if (mAsync.
isAsync())
{
mTexture = Engine.
assets.
get(mTextureFile
);
if (mSheetFile
!=
null)
def = Engine.
assets.
get(mSheetFile
);
}
else
{
// load texture synchronously
mTexture =
new Texture
(Gdx.
files.
internal(mTextureFile
));
if (mSheetFile
!=
null)
def = SpriteUtil.
readSpriteRegionInfo(Gdx.
files.
internal(mSheetFile
));
}
if ((mSheetFile
!=
null) && (mRegions ==
null))
processRegionInfo
(def
);
if (mGeometry
!=
null)
{
mGeometry.
dispose();
mGeometry =
null;
}
mGeometry = createGeometry
();
}
public void processRegionInfo
(SpriteSheetDefinition def
)
{
if ((def ==
null) ||
(def.
frames.
size() ==
0))
{
// whole texture as region
mRegions =
new SpriteSheetRegion
[1];
mRegions
[0] =
new SpriteSheetRegion
(this,
0,
0, mTexture.
getWidth()-
1, mTexture.
getHeight()-
1,
true);
return;
}
mRegions =
new SpriteSheetRegion
[def.
frames.
size()];
for (int i =
0; i
< def.
frames.
size(); i++
)
{
SpriteSheetDefinition.
FrameInfo frame = def.
frames.
get(i
);
float w = mTexture.
getWidth()-
1;
float h = mTexture.
getHeight()-
1;
float left = MathUtil.
clamp(frame.
x,
0, w
);
float top = MathUtil.
clamp(frame.
y,
0, h
);
float right = MathUtil.
clamp(frame.
x + frame.
w,
0, w
);
float bottom = MathUtil.
clamp(frame.
y + frame.
h,
0, h
);
mRegions
[i
] =
new SpriteSheetRegion
(this,
Math.
min(left, right
),
Math.
min(top, bottom
),
Math.
max(left, right
),
Math.
max(top, bottom
),
true);
}
}
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++
)
{
SpriteSheetRegion region = mRegions
[i
];
region.
regionIndex = 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 =
{
region.
left, region.
top,
region.
right, region.
top,
region.
right, region.
bottom,
region.
left, region.
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
(Geometry.
PrimitiveType.
TRIANGLES);
mesh.
setPositions(vertices
);
mesh.
setTexCoords(texCoords
);
mesh.
setColors(colors
);
mesh.
setIndices(indices
);
return mesh
;
}
public void dispose
()
{
mRegions =
null;
if (mTexture
!=
null)
{
mTexture.
dispose();
mTexture =
null;
}
if (mGeometry
!=
null)
{
mGeometry.
dispose();
mGeometry =
null;
}
}
public void render
(int regionIndex,
float alpha, Vector4 color, Vector4 fogColor
)
{
// draw sprite
Engine.
graphics.
getSpriteShader().
activate(getTexture
(), alpha, color, fogColor
);
{
Engine.
graphics.
renderStates.
blending.
setEnabled(true);
Engine.
graphics.
renderStates.
culling.
setEnabled(false);
Engine.
graphics.
renderStates.
activate();
Engine.
graphics.
renderStates.
blending.
activate(true);
{
mGeometry.
render(regionIndex
* NUM_INDICES_PER_REGION, NUM_INDICES_PER_REGION
);
}
Engine.
graphics.
renderStates.
deactivate();
}
Engine.
graphics.
getSpriteShader().
deactivate();
}
// Getters/Setters==================================================================================
public final Texture getTexture
()
{
return mTexture
;
}
public final SpriteSheetRegion getRegion
(int i
)
{
return mRegions
[i
];
}
public final int getRegionCount
()
{
return mRegions.
length;
}
}