#include "Sprite.h"
namespace NEngine
{
namespace NGFX
{
void CheckGLError();
CSprite::CSprite()
{
mpPng = new NFormats::CPng();
mpFile = new NFile::CFileSystem();
/**
* We need to load all the sprites in the "Data/Gfx/Sprites" folder
*/
std::vector<std::string> vec_folders = mpFile->GetFolders("Data/Gfx/Sprites");
std::vector<std::string> vec_files;
for(int i = 0; i < vec_folders.size(); ++i)
{
vec_files = mpFile->GetFilesInFolder(vec_folders.at(i), "*.sprite");
for(int j = 0; j < vec_files.size(); ++j)
{
LoadSprite(vec_files.at(j));
}
}
}
CSprite::~CSprite()
{
delete mpPng;
}
void CSprite::LoadSprite(std::string astrPath)
{
FILE *pF = fopen(astrPath.data(), "rb");
if(!pF)
{
REPORT("{GFX}["<< TIME<<"]Error:"<< astrPath<< " is an invalid file! <CStd File I/O>\n");
return;
}
fseek(pF, 0, SEEK_END);
int length = ftell(pF);
fseek(pF, 0, SEEK_SET);
if(length <= 0)
{
REPORT("{GFX}["<< TIME<<"]Error: "<< astrPath<< " is an empty file! <CStd File I/O>\n");
return;
}
char *vData = new char[length];
fread(vData, 1, length, pF);
ParseSpriteFile(vData);
fclose(pF);
}
void CSprite::GenerateGLDisplayList(SGfxSprite *aSprite, int aNumFrames)
{
assert(aSprite != NULL);
int iGlError = glGetError();
if(iGlError != GL_NO_ERROR)
{
REPORT("{Gfx}["<< TIME<< "]Error: "<< gluErrorString(iGlError)<< " <OpenGL>\n");
}
aSprite->iFrames = new uint[aNumFrames];
uint displayList = glGenLists(aNumFrames);
if(displayList <= 0)
{
REPORT("{Gfx}["<< TIME<< "]Error: Couldn't create OpenGL display lists! <OpenGL>\n");
return;
}
aSprite->iFrames[0] = displayList;
aSprite->iFrames[1] = displayList+1;
aSprite->iFrames[2] = displayList+2;
aSprite->iFrames[3] = displayList+3;
#ifdef DEBUG
REPORT("{Gfx}["<< TIME<< "]DEBUG: List "<< aSprite->iFrames[0]<< " created! <Sprite System>\n");
REPORT("{Gfx}["<< TIME<< "]DEBUG: List "<< aSprite->iFrames[1]<< " created! <Sprite System>\n");
REPORT("{Gfx}["<< TIME<< "]DEBUG: List "<< aSprite->iFrames[2]<< " created! <Sprite System>\n");
REPORT("{Gfx}["<< TIME<< "]DEBUG: List "<< aSprite->iFrames[3]<< " created! <Sprite System>\n");
#endif
for(int i = 0; i < aNumFrames; ++i)
{
glNewList(aSprite->iFrames[i], GL_COMPILE);
glBindTexture(GL_TEXTURE_2D, aSprite->iGLTextures[i]);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glBegin(GL_QUADS);
glTexCoord2i(0, 0);
glVertex2f(aSprite->gfxObject->sPoly->sPosition->nX, aSprite->gfxObject->sPoly->sPosition->nY);
glTexCoord2i(1, 0);
glVertex2f(aSprite->gfxObject->sPoly->sDimensions->nX, aSprite->gfxObject->sPoly->sPosition->nY);
glTexCoord2i(1, 1);
glVertex2f(aSprite->gfxObject->sPoly->sDimensions->nX, aSprite->gfxObject->sPoly->sDimensions->nY);
glTexCoord2i(0, 1);
glVertex2f(aSprite->gfxObject->sPoly->sPosition->nX, aSprite->gfxObject->sPoly->sDimensions->nY);
glEnd();
glEndList();
#ifdef DEBUG
REPORT("{Gfx}["<< TIME<< "]DEBUG: Display list "<< aSprite->iFrames[i]<< " compiled! <OpenGL>\n");
#endif
iGlError = glGetError();
if(iGlError != GL_NO_ERROR)
{
REPORT("{Gfx}["<< TIME<< "]Error: "<< gluErrorString(iGlError)<< " <OpenGL>\n");
}
if(!aSprite->iFrames[i])
{
REPORT("{Gfx}["<< TIME<< "]Error: Display list reference is not a list! <OpenGL>\n");
}
}
aSprite->currentFrame = 0;
REPORT("{Gfx}["<< TIME<< "]Information: OpenGL Display lists for "<< aSprite->str_Name<< " was successfully created! <Sprite System>\n");
}
void CSprite::PaintSpriteByName(std::string aStrName)
{
int iGlError = glGetError();
if(iGlError != GL_NO_ERROR)
{
REPORT("{Gfx}["<< TIME<< "]Error: "<< gluErrorString(iGlError)<< " <OpenGL>\n");
}
for(int i = 0; i < vec_Sprites.size(); ++i)
{
SGfxSprite *sCurrSprite = &vec_Sprites.at(i);
if(!strcmp(sCurrSprite->str_Name.data(), aStrName.data()))
{
if(sCurrSprite->currentFrame >= DIM(sCurrSprite->iGLTextures))
{
sCurrSprite->currentFrame = 0;
}
else
{
++sCurrSprite->currentFrame;
}
glBindTexture(GL_TEXTURE_2D, sCurrSprite->iGLTextures[0]);
glCallList(sCurrSprite->iFrames[0]);
}
}
iGlError = glGetError();
if(iGlError != GL_NO_ERROR)
{
REPORT("{Gfx}["<< TIME<< "]Error: "<< gluErrorString(iGlError)<< " <OpenGL>\n");
}
}
void CSprite::ParseSpriteFile(char aData[])
{
CheckGLError();
/**
* The scripts are setup like so:
***********************************************
* Pngs:
* 4; // This is the number of frames.
* <pngname>_001.png;
* <pngname>_002.png;
* <pngname>_003.png;
* <pngname>_004.png;
*
* Properties:
* name=<obj name>;
* width=###;
* height=###;
************************************************
*/
vec_Sprites.push_back(SGfxSprite("",
new SGraphicsObject(EPhysicsObjectShape_Quad,
new SPoly(new SVec2D(0, 0), new SVec2D(0, 0)))));
char *pPngStr = new char[4096];
pPngStr = strtok(aData, "\n");
pPngStr = strtok(NULL, "\n");
int iNumFrames = atoi(pPngStr);
#ifdef DEBUG
REPORT("{Gfx}["<< TIME<< "]DEBUG: Number of frames: "<< iNumFrames<< " <Sprite System>\n");
#endif
vec_Sprites.at(vec_Sprites.size()-1).iGLTextures = new uint[iNumFrames];
glGenTextures(iNumFrames, vec_Sprites.at(vec_Sprites.size()-1).iGLTextures);
int i = 0; // used for loop only!
while(pPngStr != NULL)
{
pPngStr = strtok(NULL, "\n");
if(!strcmp(pPngStr, "Properties:") || i >= iNumFrames)
{
break;
}
if(mpPng->LoadPng(pPngStr))
{
CheckGLError();
glBindTexture(GL_TEXTURE_2D, vec_Sprites.at(vec_Sprites.size()-1).iGLTextures[i]);
CheckGLError();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
CheckGLError();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
CheckGLError();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
CheckGLError();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
CheckGLError();
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
CheckGLError();
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mpPng->miWidth, mpPng->miHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, mpPng->mpData);
CheckGLError();
#ifdef DEBUG
REPORT("{Gfx}["<< TIME<< "]DEBUG: Created texture for "<< pPngStr<< " at "<< vec_Sprites.at(vec_Sprites.size()-1).iGLTextures[i]<<"! <OpenGL>\n");
#endif
CheckGLError();
}
if(!glIsTexture(vec_Sprites.at(vec_Sprites.size()-1).iGLTextures[i]))
{
REPORT("{Gfx}["<< TIME<< "]Error: Texture reference is not a texture! <OpenGL>\n");
}
++i;
}
pPngStr = strtok(NULL, "=\n");
pPngStr = strtok(NULL, "\n");
std::string str_name = pPngStr;
#ifdef DEBUG
REPORT("{Gfx}["<< TIME<< "]DEBUG: Sprite name: "<< str_name<< " <Sprite System>\n");
#endif
pPngStr = strtok(NULL, "=\n");
pPngStr = strtok(NULL, "\n");
int iWidth = atoi(pPngStr);
#ifdef DEBUG
REPORT("{Gfx}["<< TIME<< "]DEBUG: Sprite width(pixels): "<< iWidth<< " <Sprite System>\n");
#endif
pPngStr = strtok(NULL, "=\n");
pPngStr = strtok(NULL, "\n");
int iHeight = atoi(pPngStr);
#ifdef DEBUG
REPORT("{Gfx}["<< TIME<< "]DEBUG: Sprite height(pixels): "<< iHeight<< " <Sprite System>\n");
#endif
vec_Sprites.at(vec_Sprites.size()-1).str_Name = str_name;
vec_Sprites.at(vec_Sprites.size()-1).gfxObject->sPoly->sDimensions->nX = iWidth;
vec_Sprites.at(vec_Sprites.size()-1).gfxObject->sPoly->sDimensions->nY = iHeight;
GenerateGLDisplayList(&vec_Sprites.at(vec_Sprites.size()-1), iNumFrames);
#ifdef DEBUG
REPORT("{Gfx}["<< TIME<< "]DEBUG: Sprite("<< str_name<<") OpenGL textures: \n\t"<<
vec_Sprites.at(vec_Sprites.size()-1).iGLTextures[0]<<
"\n\t"<< vec_Sprites.at(vec_Sprites.size()-1).iGLTextures[1]<<
"\n\t"<< vec_Sprites.at(vec_Sprites.size()-1).iGLTextures[2]<<
"\n\t"<< vec_Sprites.at(vec_Sprites.size()-1).iGLTextures[3]<< " <Sprite System>\n");
#endif
CheckGLError();
}
void CheckGLError()
{
int iGlError = glGetError();
if(iGlError != GL_NO_ERROR)
{
REPORT("{Gfx}["<< TIME<< "]Error: "<< gluErrorString(iGlError)<< " <OpenGL>\n");
}
}
}
}