using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using BauzoidNET.math;
using BauzoidNET.graphics.renderstates;
using BauzoidNET.graphics.texture;
using BauzoidNET.graphics.model;
using Tao.OpenGl;
namespace BauzoidNET
.graphics.sprite
{
public class Sprite
: GraphicsObject
{
public const int NUM_INDICES_PER_REGION
= 6;
public const int NUM_ATTRIBUTES_PER_REGION
= 4;
protected Texture mTexture
= null;
private SpriteRegion
[] mRegions
= null;
protected SimpleGeometry mMesh
= null;
protected String mTextureFilename
= null;
protected Bitmap mTextureBitmap
= null;
protected String mRegionDefFilename
= null;
/** Constructor. Does not load anything yet
*/
public Sprite
(Graphics graphics,
String filename
)
: base(graphics
)
{
mTextureFilename
= filename
;
}
public Sprite
(Graphics graphics, Bitmap bm
)
: base(graphics
)
{
mTextureBitmap
= bm
;
}
public Sprite
(Graphics graphics,
String textureFile,
String atlasFile
)
: this(graphics, textureFile
)
{
mRegionDefFilename
= atlasFile
;
}
public Sprite
(Graphics graphics, Bitmap bm,
String atlasFile
)
: this(graphics, bm
)
{
mRegionDefFilename
= atlasFile
;
}
public void init
()
{
if ((mTextureFilename
== null) && (mTextureBitmap
== null))
return;
// load texture synchronously
if (mTextureFilename
!= null)
mTexture
= new Texture
(getGraphics
(), mTextureFilename
);
else if (mTextureBitmap
!= null)
mTexture
= new Texture
(getGraphics
(), mTextureBitmap
);
if (mRegionDefFilename
!= null)
{
List
<SpriteUtil
.SpriteRegionInfo> atlas
= SpriteUtil
.readSpriteRegionInfo(mRegionDefFilename
);
SpriteRegion
[] regions
= new SpriteRegion
[atlas
.Count];
for (int i
= 0; i
< atlas
.Count; i
++)
{
regions
[i
] = new SpriteRegion
(this, i, atlas
[i
].x, atlas
[i
].y, atlas
[i
].w, atlas
[i
].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
);
}
}
public void dispose
()
{
if (mRegions
!= null)
mRegions
= null;
if (mTexture
!= null)
{
mTexture
.dispose();
mTexture
= null;
}
}
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
};
Array
.Copy(v,
0, vertices, NUM_ATTRIBUTES_PER_REGION
* SimpleGeometry
.POSITION_COORD_PER_ELEMENT * i, v
.Length);
Array
.Copy(t,
0, texCoords, NUM_ATTRIBUTES_PER_REGION
* SimpleGeometry
.TEXCOORD_COORD_PER_ELEMENT * i, t
.Length);
Array
.Copy(c,
0, colors, NUM_ATTRIBUTES_PER_REGION
* SimpleGeometry
.COLOR_COORD_PER_ELEMENT * i, c
.Length);
int n
= i
*NUM_INDICES_PER_REGION
;
short baseIndex
= (short)(i
* NUM_ATTRIBUTES_PER_REGION
);
indices
[n
++] = baseIndex
; indices
[n
++] = (short)(baseIndex
+ 1); indices
[n
++] = (short)(baseIndex
+ 2);
indices
[n
++] = baseIndex
; indices
[n
++] = (short)(baseIndex
+ 2); indices
[n
++] = (short)(baseIndex
+ 3);
}
SimpleGeometry mesh
= new SimpleGeometry
(getGraphics
(), Geometry
.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 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();
}
/** Get the sprite texture's total width. */
public int getTextureWidth
()
{
if (mTexture
== null)
return 0;
return mTexture
.getWidth();
}
/** Get the sprite texture's total height. */
public int getTextureHeight
()
{
if (mTexture
== null)
return 0;
return mTexture
.getHeight();
}
/** Get a reference to the texture. */
public Texture getTexture
()
{
return mTexture
;
}
/** Set a new texture, with the old one (if any) getting destroyed. */
public void setTexture
(Texture texture
)
{
if (mTexture
!= null)
mTexture
.dispose();
mTexture
= texture
;
}
/** Get number of defined regions. */
public int getRegionCount
()
{
if (mRegions
== null)
return 0;
return mRegions
.Length;
}
/** Get region. */
public SpriteRegion getRegion
(int i
)
{
if (mRegions
== null)
return null;
return mRegions
[i
];
}
/** Get regions array.*/
public SpriteRegion
[] getRegions
()
{
return mRegions
;
}
/** Get starting index for region mesh rendering. */
private int getMeshStartIndex
(int regionIndex
)
{
return (regionIndex
* NUM_INDICES_PER_REGION
);
}
}
}