/*
** Haaf's Game Engine 1.7
** Copyright (C) 2003-2007, Relish Games
** hge.relishgames.com
**
** hgeResourceManager resources implementation
*/
#include "../../include/hgeresource.h"
#include "parser.h"
#include "resources.h"
HGE *ResDesc::hge=0;
/////////////// COMMON //
void AddRes(hgeResourceManager *rm, int type, ResDesc *resource)
{
resource->next=rm->res[type];
rm->res[type]=resource;
}
ResDesc *FindRes(hgeResourceManager *rm, int type, const char *name)
{
ResDesc *rc;
rc=rm->res[type];
while(rc)
{
if(!strcmp(name, rc->name)) return rc;
rc=rc->next;
}
return 0;
}
bool ScriptSkipToNextParameter(RScriptParser *sp, bool bIgnore)
{
bool bToBeIgnored=bIgnore;
if(bIgnore) sp->put_back();
for(;;)
{
sp->get_token();
if(sp->tokentype == TTCLOSEBLOCK) { if(bIgnore) {sp->put_back(); return true;} return false; }
if((sp->tokentype > TTRES__FIRST && sp->tokentype < TTRES__LAST) || sp->tokentype == TTEND)
{
sp->put_back();
if(bIgnore) return true;
sp->ScriptPostError("'}' missed, "," encountered.");
return false;
}
if((sp->tokentype <= TTPAR__FIRST && sp->tokentype >= TTPAR__LAST) || bToBeIgnored)
{
bToBeIgnored=false;
sp->ScriptPostError("Unsupported resource parameter ",".");
do sp->get_token();
while((sp->tokentype <= TTPAR__FIRST || sp->tokentype >= TTPAR__LAST) &&
(sp->tokentype <= TTRES__FIRST || sp->tokentype >= TTRES__LAST) &&
sp->tokentype != TTCLOSEBLOCK && sp->tokentype != TTEND);
sp->put_back();
}
else
{
if(bIgnore) sp->put_back();
return true;
}
}
}
void ScriptParseFileResource(hgeResourceManager *rm, RScriptParser *sp, const char *name, const char *basename, ResDesc *rr, int restype)
{
RResource *rc=(RResource *)rr, *base;
base = (RResource *)FindRes(rm, restype, basename);
if(base) *rc=*base; else
{
rc->resgroup=0;
rc->filename[0]=0;
}
rc->handle=0; strcpy(rc->name, name);
while(ScriptSkipToNextParameter(sp,false))
{
switch(sp->tokentype)
{
case TTPAR_FILENAME:
sp->get_token(); sp->get_token();
strcpy(rc->filename, sp->tkn_string());
break;
case TTPAR_RESGROUP:
sp->get_token(); sp->get_token();
rc->resgroup=sp->tkn_int();
break;
default:
ScriptSkipToNextParameter(sp,true);
break;
}
}
AddRes(rm, restype, rc);
}
void ScriptParseBlendMode(RScriptParser *sp, int *blend)
{
for(;;)
{
sp->get_token();
if(sp->tokentype != TTEQUALS && sp->tokentype != TTSEPARATOR) { sp->put_back(); return; }
switch(sp->get_token())
{
case TTCON_COLORMUL:
*blend &= ~BLEND_COLORADD;
break;
case TTCON_COLORADD:
*blend |= BLEND_COLORADD;
break;
case TTCON_ALPHABLND:
*blend |= BLEND_ALPHABLEND;
break;
case TTCON_ALPHAADD:
*blend &= ~BLEND_ALPHABLEND;
break;
case TTCON_ZWRITE:
*blend |= BLEND_ZWRITE;
break;
case TTCON_NOZWRITE:
*blend &= ~BLEND_ZWRITE;
break;
default:
sp->ScriptPostError("Unsupported value ",".");
break;
}
}
}
void ScriptParseSpriteAnim(RScriptParser *sp, RSprite *rc, bool anim)
{
while(ScriptSkipToNextParameter(sp,false))
{
switch(sp->tokentype)
{
case TTPAR_TEXTURE:
sp->get_token(); sp->get_token();
strcpy(rc->texname,sp->tkn_string());
break;
case TTPAR_RECT:
sp->get_token(); sp->get_token();
rc->tx=sp->tkn_float();
sp->get_token(); sp->get_token();
rc->ty=sp->tkn_float();
sp->get_token(); sp->get_token();
rc->w=sp->tkn_float();
sp->get_token(); sp->get_token();
rc->h=sp->tkn_float();
break;
case TTPAR_HOTSPOT:
sp->get_token(); sp->get_token();
rc->hotx=sp->tkn_float();
sp->get_token(); sp->get_token();
rc->hoty=sp->tkn_float();
break;
case TTPAR_BLENDMODE:
ScriptParseBlendMode(sp, &rc->blend);
break;
case TTPAR_COLOR:
sp->get_token(); sp->get_token();
rc->color=sp->tkn_hex();
break;
case TTPAR_ZORDER:
sp->get_token(); sp->get_token();
rc->z=sp->tkn_float();
break;
case TTPAR_FLIP:
sp->get_token(); sp->get_token();
rc->bXFlip=sp->tkn_bool();
sp->get_token(); sp->get_token();
rc->bYFlip=sp->tkn_bool();
break;
case TTPAR_RESGROUP:
sp->get_token(); sp->get_token();
rc->resgroup=sp->tkn_int();
break;
case TTPAR_FRAMES:
if(anim)
{
sp->get_token(); sp->get_token();
((RAnimation *)rc)->frames=sp->tkn_int();
break;
}
case TTPAR_FPS:
if(anim)
{
sp->get_token(); sp->get_token();
((RAnimation *)rc)->fps=sp->tkn_float();
break;
}
case TTPAR_MODE:
if(anim)
{
for(;;)
{
sp->get_token();
if(sp->tokentype != TTEQUALS && sp->tokentype != TTSEPARATOR) { sp->put_back(); break; }
switch(sp->get_token())
{
case TTCON_FORWARD:
((RAnimation *)rc)->mode &= ~HGEANIM_REV;
break;
case TTCON_REVERSE:
((RAnimation *)rc)->mode |= HGEANIM_REV;
break;
case TTCON_NOPINGPONG:
((RAnimation *)rc)->mode &= ~HGEANIM_PINGPONG;
break;
case TTCON_PINGPONG:
((RAnimation *)rc)->mode |= HGEANIM_PINGPONG;
break;
case TTCON_NOLOOP:
((RAnimation *)rc)->mode &= ~HGEANIM_LOOP;
break;
case TTCON_LOOP:
((RAnimation *)rc)->mode |= HGEANIM_LOOP;
break;
default:
sp->ScriptPostError("Unsupported value ",".");
break;
}
}
break;
}
default:
ScriptSkipToNextParameter(sp,true);
break;
}
}
}
/////////////// RScript //
void RScript::Parse(hgeResourceManager *rm, RScriptParser *sp, const char *sname, const char *sbasename)
{
RScriptParser *np;
RScript *res_script;
void *data;
DWORD size;
char *script, name[MAXRESCHARS], basename[MAXRESCHARS];
int restype;
if(!FindRes(rm, RES_SCRIPT, sname))
{
res_script = new RScript(); // hack! we need an instance of RScript to access hge
// if all ok, this object is used later to keep the script
data=hge->Resource_Load(sname, &size);
if(!data)
{
if(sp) sp->ScriptPostError("Script "," not found.");
else hge->System_Log("Script '%s' not found.",sname);
delete res_script;
return;
}
else
{
script= new char[size+1];
memcpy(script, data, size);
script[size]=0;
hge->Resource_Free(data);
strcpy(res_script->name, sname);
AddRes(rm, RES_SCRIPT, res_script);
np = new RScriptParser(res_script->name, script);
for(;;)
{
np->get_token();
if(np->tokentype == TTEND) break;
else if(np->tokentype == TTRES_INCLUDE)
{
np->get_token();
RScript::Parse(rm, np, np->tkn_string(), NULL);
}
else if(np->tokentype > TTRES__FIRST && np->tokentype < TTRES__LAST)
{
restype=np->tokentype-TTRES__FIRST-1;
name[0]=basename[0]=0;
np->get_token();
if(FindRes(rm, restype, np->tkn_string()))
{
np->ScriptPostError("Resource "," of the same type already has been defined.");
while((np->tokentype <= TTRES__FIRST || np->tokentype >= TTRES__LAST) && np->tokentype != TTEND) np->get_token();
np->put_back();
continue;
}
strcpy(name, np->tkn_string());
np->get_token();
if(np->tokentype == TTBASED)
{
np->get_token();
if(!FindRes(rm, restype, np->tkn_string())) np->ScriptPostError("Base resource "," is not defined.");
else strcpy(basename, np->tkn_string());
np->get_token();
}
if(np->tokentype == TTOPENBLOCK)
{
switch(restype)
{
case RES_RESOURCE: RResource::Parse(rm, np, name, basename); break;
case RES_TEXTURE: RTexture::Parse(rm, np, name, basename); break;
case RES_EFFECT: REffect::Parse(rm, np, name, basename); break;
case RES_TARGET: RTarget::Parse(rm, np, name, basename); break;
case RES_SPRITE: RSprite::Parse(rm, np, name, basename); break;
case RES_ANIMATION: RAnimation::Parse(rm, np, name, basename); break;
case RES_FONT: RFont::Parse(rm, np, name, basename); break;
case RES_PARTICLE: RParticle::Parse(rm, np, name, basename); break;
case RES_DISTORT: RDistort::Parse(rm, np, name, basename); break;
case RES_STRTABLE: RStringTable::Parse(rm, np, name, basename); break;
}
}
else
{
np->ScriptPostError("Illegal resource syntax, "," found; '{' expected.");
while((np->tokentype <= TTRES__FIRST || np->tokentype >= TTRES__LAST) && np->tokentype != TTEND) np->get_token();
np->put_back();
}
}
else
{
np->ScriptPostError("Unrecognized resource specificator ",".");
while((np->tokentype <= TTRES__FIRST || np->tokentype >= TTRES__LAST) && np->tokentype != TTEND) np->get_token();
np->put_back();
}
}
delete np;
delete[] script;
}
}
else sp->ScriptPostError("Script "," already has been parsed.");
}
/////////////// RResource //
void RResource::Parse(hgeResourceManager *rm, RScriptParser *sp, const char *name, const char *basename)
{
ScriptParseFileResource(rm, sp, name, basename, new RResource(), RES_RESOURCE);
}
DWORD RResource::Get(hgeResourceManager *rm)
{
if(!handle) handle=(size_t)hge->Resource_Load(filename);
return handle;
}
void RResource::Free()
{
if(handle) hge->Resource_Free((void *)handle);
handle=0;
}
/////////////// RTexture //
void RTexture::Parse(hgeResourceManager *rm, RScriptParser *sp, const char *name, const char *basename)
{
RTexture *rc, *base;
rc=new RTexture();
base = (RTexture *)FindRes(rm, RES_TEXTURE, basename);
if(base) *rc=*base;
else
{
rc->resgroup=0;
rc->mipmap=false;
}
rc->handle=0; strcpy(rc->name, name);
while(ScriptSkipToNextParameter(sp,false))
{
switch(sp->tokentype)
{
case TTPAR_FILENAME:
sp->get_token(); sp->get_token();
strcpy(rc->filename, sp->tkn_string());
break;
case TTPAR_RESGROUP:
sp->get_token(); sp->get_token();
rc->resgroup=sp->tkn_int();
break;
case TTPAR_MIPMAP:
sp->get_token(); sp->get_token();
rc->mipmap=sp->tkn_bool();
break;
default:
ScriptSkipToNextParameter(sp,true);
break;
}
}
AddRes(rm, RES_TEXTURE, rc);
}
DWORD RTexture::Get(hgeResourceManager *rm)
{
if(!handle) handle=(DWORD)hge->Texture_Load(filename, 0, mipmap);
return handle;
}
void RTexture::Free()
{
if(handle) hge->Texture_Free((HTEXTURE)handle);
handle=0;
}
/////////////// REffect //
void REffect::Parse(hgeResourceManager *rm, RScriptParser *sp, const char *name, const char *basename)
{
ScriptParseFileResource(rm, sp, name, basename, new REffect(), RES_EFFECT);
}
DWORD REffect::Get(hgeResourceManager *rm)
{
if(!handle) handle=(DWORD)hge->Effect_Load(filename);
return handle;
}
void REffect::Free()
{
if(handle) hge->Effect_Free((HEFFECT)handle);
handle=0;
}
/////////////// RTarget //
void RTarget::Parse(hgeResourceManager *rm, RScriptParser *sp, const char *name, const char *basename)
{
RTarget *rc, *base;
rc = new RTarget();
base = (RTarget *)FindRes(rm, RES_TARGET, basename);
if(base) *rc=*base;
else
{
rc->resgroup=0;
rc->width=256;
rc->height=256;
rc->zbuffer=false;
}
rc->handle=0; strcpy(rc->name, name);
while(ScriptSkipToNextParameter(sp, false))
{
switch(sp->tokentype)
{
case TTPAR_SIZE:
sp->get_token(); sp->get_token();
rc->width=sp->tkn_int();
sp->get_token();
sp->get_token();
rc->height=sp->tkn_int();
break;
case TTPAR_ZBUFFER:
sp->get_token(); sp->get_token();
rc->zbuffer=sp->tkn_bool();
break;
case TTPAR_RESGROUP:
sp->get_token(); sp->get_token();
rc->resgroup=sp->tkn_int();
break;
default:
ScriptSkipToNextParameter(sp, true);
break;
}
}
AddRes(rm, RES_TARGET, rc);
}
DWORD RTarget::Get(hgeResourceManager *rm)
{
if(!handle) handle=(DWORD)hge->Target_Create(width, height, zbuffer);
return handle;
}
void RTarget::Free()
{
if(handle) hge->Target_Free((HTARGET)handle);
handle=0;
}
/////////////// RSprite //
void RSprite::Parse(hgeResourceManager *rm, RScriptParser *sp, const char *name, const char *basename)
{
RSprite *rc, *base;
rc = new RSprite();
base = (RSprite *)FindRes(rm, RES_SPRITE, basename);
if(base) *rc=*base;
else
{
rc->resgroup=0;
rc->texname[0]=0;
rc->tx=rc->ty=0;
rc->w=rc->h=0;
rc->hotx=rc->hoty=0;
rc->blend=BLEND_COLORMUL | BLEND_ALPHABLEND | BLEND_NOZWRITE;
rc->color=0xFFFFFFFF;
rc->z=0.5f;
rc->bXFlip=false;
rc->bYFlip=false;
// rc->x=rc->y=0;
// rc->scale=1.0f;
// rc->rotation=0.0f;
// rc->collision=HGECOL_RECT;
}
rc->handle=0;
strcpy(rc->name, name);
ScriptParseSpriteAnim(sp, rc, false);
AddRes(rm, RES_SPRITE, rc);
}
DWORD RSprite::Get(hgeResourceManager *rm)
{
hgeSprite *spr;
if(!handle)
{
spr = new hgeSprite(rm->GetTexture(texname, resgroup), tx, ty, w, h);
spr->SetColor(color);
spr->SetZ(z);
spr->SetBlendMode(blend);
spr->SetHotSpot(hotx,hoty);
spr->SetFlip(bXFlip, bYFlip);
// spr->MoveTo(x,y);
// spr->SetScale(scale);
// spr->SetRotation(rotation);
// spr->SetCollisionType(collision);
handle=(size_t)spr;
}
return handle;
}
void RSprite::Free()
{
if(handle) delete (hgeSprite *)handle;
handle=0;
}
/////////////// RAnimation //
void RAnimation::Parse(hgeResourceManager *rm, RScriptParser *sp, const char *name, const char *basename)
{
RAnimation *rc, *base;
rc = new RAnimation();
base = (RAnimation *)FindRes(rm, RES_ANIMATION, basename);
if(base) *rc=*base;
else
{
rc->resgroup=0;
rc->texname[0]=0;
rc->tx=rc->ty=0;
rc->w=rc->h=0;
rc->hotx=rc->hoty=0;
rc->blend=BLEND_COLORMUL | BLEND_ALPHABLEND | BLEND_NOZWRITE;
rc->color=0xFFFFFFFF;
rc->z=0.5f;
rc->bXFlip=false;
rc->bYFlip=false;
// rc->x=rc->y=0;
// rc->scale=1.0f;
// rc->rotation=0.0f;
// rc->collision=HGECOL_RECT;
rc->frames=1;
rc->fps=12.0f;
rc->mode=HGEANIM_FWD | HGEANIM_LOOP;
}
rc->handle=0;
strcpy(rc->name, name);
ScriptParseSpriteAnim(sp, rc, true);
AddRes(rm, RES_ANIMATION, rc);
}
DWORD RAnimation::Get(hgeResourceManager *rm)
{
hgeAnimation *spr;
if(!handle)
{
spr = new hgeAnimation(rm->GetTexture(texname, resgroup), frames, fps, tx, ty, w, h);
spr->SetColor(color);
spr->SetZ(z);
spr->SetBlendMode(blend);
spr->SetHotSpot(hotx,hoty);
spr->SetFlip(bXFlip, bYFlip);
// spr->MoveTo(x,y);
// spr->SetScale(scale);
// spr->SetRotation(rotation);
// spr->SetCollisionType(collision);
spr->SetMode(mode);
handle=(size_t)spr;
}
return handle;
}
void RAnimation::Free()
{
if(handle) delete (hgeAnimation *)handle;
handle=0;
}
/////////////// RFont //
void RFont::Parse(hgeResourceManager *rm, RScriptParser *sp, const char *name, const char *basename)
{
RFont *rc, *base;
rc = new RFont();
base = (RFont *)FindRes(rm, RES_FONT, basename);
if(base) *rc=*base;
else
{
rc->resgroup=0;
rc->mipmap=false;
rc->filename[0]=0;
rc->blend=BLEND_COLORMUL | BLEND_ALPHABLEND | BLEND_NOZWRITE;
rc->color=0xFFFFFFFF;
rc->z=0.5f;
rc->scale=1.0f;
rc->proportion=1.0f;
rc->tracking=0.0f;
rc->spacing=1.0f;
rc->rotation=0.0f;
}
rc->handle=0; strcpy(rc->name, name);
while(ScriptSkipToNextParameter(sp,false))
{
switch(sp->tokentype)
{
case TTPAR_FILENAME:
sp->get_token(); sp->get_token();
strcpy(rc->filename, sp->tkn_string());
break;
case TTPAR_BLENDMODE:
ScriptParseBlendMode(sp, &rc->blend);
break;
case TTPAR_COLOR:
sp->get_token(); sp->get_token();
rc->color=sp->tkn_hex();
break;
case TTPAR_ZORDER:
sp->get_token(); sp->get_token();
rc->z=sp->tkn_float();
break;
case TTPAR_SCALE:
sp->get_token(); sp->get_token();
rc->scale=sp->tkn_float();
break;
case TTPAR_PROPORTION:
sp->get_token(); sp->get_token();
rc->proportion=sp->tkn_float();
break;
case TTPAR_ROTATION:
sp->get_token(); sp->get_token();
rc->rotation=sp->tkn_float();
break;
case TTPAR_TRACKING:
sp->get_token(); sp->get_token();
rc->tracking=sp->tkn_float();
break;
case TTPAR_SPACING:
sp->get_token(); sp->get_token();
rc->spacing=sp->tkn_float();
break;
case TTPAR_RESGROUP:
sp->get_token(); sp->get_token();
rc->resgroup=sp->tkn_int();
break;
case TTPAR_MIPMAP:
sp->get_token(); sp->get_token();
rc->mipmap=sp->tkn_bool();
break;
default:
ScriptSkipToNextParameter(sp, true);
break;
}
}
AddRes(rm, RES_FONT, rc);
}
DWORD RFont::Get(hgeResourceManager *rm)
{
hgeFont *fnt;
if(!handle)
{
fnt = new hgeFont(filename, mipmap);
fnt->SetColor(color);
fnt->SetZ(z);
fnt->SetBlendMode(blend);
fnt->SetScale(scale);
fnt->SetProportion(proportion);
fnt->SetTracking(tracking);
fnt->SetSpacing(spacing);
fnt->SetRotation(rotation);
handle=(size_t)fnt;
}
return handle;
}
void RFont::Free()
{
if(handle) delete (hgeFont *)handle;
handle=0;
}
/////////////// RParticle //
void RParticle::Parse(hgeResourceManager *rm, RScriptParser *sp, const char *name, const char *basename)
{
RParticle *rc, *base;
rc = new RParticle();
base = (RParticle *)FindRes(rm, RES_PARTICLE, basename);
if(base) *rc=*base;
else
{
rc->resgroup=0;
rc->filename[0]=0;
rc->spritename[0]=0;
}
rc->handle=0; strcpy(rc->name, name);
while(ScriptSkipToNextParameter(sp, false))
{
switch(sp->tokentype)
{
case TTPAR_FILENAME:
sp->get_token(); sp->get_token();
strcpy(rc->filename, sp->tkn_string());
break;
case TTPAR_SPRITE:
sp->get_token(); sp->get_token();
strcpy(rc->spritename, sp->tkn_string());
break;
case TTPAR_RESGROUP:
sp->get_token(); sp->get_token();
rc->resgroup=sp->tkn_int();
break;
default:
ScriptSkipToNextParameter(sp, true);
break;
}
}
AddRes(rm, RES_PARTICLE, rc);
}
DWORD RParticle::Get(hgeResourceManager *rm)
{
hgeParticleSystem *par;
if(!handle)
{
par = new hgeParticleSystem(filename, rm->GetSprite(spritename));
handle=(size_t)par;
}
return handle;
}
void RParticle::Free()
{
if(handle) delete (hgeParticleSystem *)handle;
handle=0;
}
/////////////// RDistort //
void RDistort::Parse(hgeResourceManager *rm, RScriptParser *sp, const char *name, const char *basename)
{
RDistort *rc, *base;
rc = new RDistort();
base = (RDistort *)FindRes(rm, RES_DISTORT, basename);
if(base) *rc=*base;
else
{
rc->resgroup=0;
rc->texname[0]=0;
rc->tx=rc->ty=0;
rc->w=rc->h=0;
rc->cols=rc->rows=2;
rc->blend=BLEND_COLORMUL | BLEND_ALPHABLEND | BLEND_NOZWRITE;
rc->color=0xFFFFFFFF;
rc->z=0.5f;
}
rc->handle=0; strcpy(rc->name, name);
while(ScriptSkipToNextParameter(sp, false))
{
switch(sp->tokentype)
{
case TTPAR_TEXTURE:
sp->get_token(); sp->get_token();
strcpy(rc->texname, sp->tkn_string());
break;
case TTPAR_RECT:
sp->get_token(); sp->get_token();
rc->tx=sp->tkn_float();
sp->get_token(); sp->get_token();
rc->ty=sp->tkn_float();
sp->get_token(); sp->get_token();
rc->w=sp->tkn_float();
sp->get_token(); sp->get_token();
rc->h=sp->tkn_float();
break;
case TTPAR_MESH:
sp->get_token(); sp->get_token();
rc->cols=sp->tkn_int();
sp->get_token(); sp->get_token();
rc->rows=sp->tkn_int();
break;
case TTPAR_BLENDMODE:
ScriptParseBlendMode(sp, &rc->blend);
break;
case TTPAR_COLOR:
sp->get_token(); sp->get_token();
rc->color=sp->tkn_hex();
break;
case TTPAR_ZORDER:
sp->get_token(); sp->get_token();
rc->z=sp->tkn_float();
break;
case TTPAR_RESGROUP:
sp->get_token(); sp->get_token();
rc->resgroup=sp->tkn_int();
break;
default:
ScriptSkipToNextParameter(sp, true);
break;
}
}
AddRes(rm, RES_DISTORT, rc);
}
DWORD RDistort::Get(hgeResourceManager *rm)
{
hgeDistortionMesh *dis;
if(!handle)
{
dis = new hgeDistortionMesh(cols, rows);
dis->SetTexture(rm->GetTexture(texname, resgroup));
dis->SetTextureRect(tx,ty,w,h);
dis->SetBlendMode(blend);
dis->Clear(color,z);
handle=(size_t)dis;
}
return handle;
}
void RDistort::Free()
{
if(handle) delete (hgeDistortionMesh *)handle;
handle=0;
}
/////////////// RStringTable //
void RStringTable::Parse(hgeResourceManager *rm, RScriptParser *sp, const char *name, const char *basename)
{
ScriptParseFileResource(rm, sp, name, basename, new RStringTable(), RES_STRTABLE);
}
DWORD RStringTable::Get(hgeResourceManager *rm)
{
if(!handle) handle = (size_t)new hgeStringTable(filename);
return handle;
}
void RStringTable::Free()
{
if(handle) delete (hgeStringTable *)handle;
handle=0;
}