hostile-takeover/game/texatlasmgr.cpp
2017-10-21 20:28:28 -04:00

195 lines
4.7 KiB
C++

#include "ht.h"
#include "yajl/wrapper/jsonbuilder.h"
#include "base/thread.h"
namespace wi {
TexAtlasMgr::TexAtlasMgr()
{
m_json = NULL;
m_pbmAtlases = NULL;
m_natlases = 0;
}
TexAtlasMgr::~TexAtlasMgr()
{
delete m_json;
m_json = NULL;
for (int n = 0; n < m_natlases; n++) {
if (m_pbmAtlases[n] != NULL)
delete m_pbmAtlases[n];
}
delete[] m_pbmAtlases;
m_pbmAtlases = NULL;
}
char *apszatlases[] = {
"animations.png",
"fonts.png",
"bitmaps.png",
"bitmaps0.png",
"bitmaps1.png",
"bitmaps2.png",
"bitmaps3.png",
"bitmaps4.png",
"units0.png",
"units1.png",
"units2.png",
"units3.png",
"units4.png"
};
bool TexAtlasMgr::Init()
{
m_natlases = ARRAYSIZE(apszatlases);
m_pbmAtlases = new DibBitmap*[m_natlases];
// Load atlases
for (int i = 0; i < m_natlases; i++) {
m_pbmAtlases[i] = LoadDibBitmap(apszatlases[i]);
if (!m_pbmAtlases[i])
return false;
}
// Read json
FileMap fmap;
char *pszJson = (char *)gpakr.MapFile("atlasmap.json", &fmap);
if (!pszJson) {
return false;
}
// Parse json
json::JsonBuilder builder;
builder.Start();
if (!builder.Update(pszJson, (int)strlen(pszJson))) {
gpakr.UnmapFile(&fmap);
return false;
}
json::JsonObject *obj = builder.End();
if (obj == NULL) {
gpakr.UnmapFile(&fmap);
return false;
}
m_json = (json::JsonMap *)obj;
gpakr.UnmapFile(&fmap);
return true;
}
void TexAtlasMgr::BltTo(TBitmap *ptbmSrc, DibBitmap *pbmDst, int xDst, int yDst, Side side, Rect *prcSrc)
{
Size siz;
ptbmSrc->GetTextureSize(&siz);
Point pt;
ptbmSrc->GetPosition(&pt);
// Where do we want to blt from?
Rect rc;
if (prcSrc != NULL) {
// NOTE: the clipping rect calculated in this block has not been
// tested with an image that was was cropped by the atlas packer
// prcSrc data needs to be converted to work within the texture atlas
rc.left = pt.x + prcSrc->left - ptbmSrc->ClippedLeft();
rc.top = pt.y + prcSrc->top - ptbmSrc->ClippedTop();
rc.right = rc.left + prcSrc->Width();
rc.bottom = rc.top + prcSrc->Height();
// Set to image edge if anything is past image edge
// to prevent other images in the texture from being
// in the blt
if (rc.left < pt.x)
rc.left = pt.x;
if (rc.top < pt.y)
rc.top = pt.y;
if (rc.right > pt.x + siz.cx)
rc.right = pt.x + siz.cx;
if (rc.bottom > pt.y + siz.cy)
rc.bottom = pt.y + siz.cy;
} else {
// No prcSrc, the blt rect is just the location and size of the image
rc.Set(pt.x, pt.y, pt.x + siz.cx , pt.y + siz.cy);
}
if (m_pbmAtlases[ptbmSrc->GetAtlas(side)]) {
pbmDst->Blt(m_pbmAtlases[ptbmSrc->GetAtlas(side)],
&rc, xDst + ptbmSrc->ClippedLeft(), yDst + ptbmSrc->ClippedTop());
}
}
TBitmap *TexAtlasMgr::CreateTBitmap(char *pszName)
{
json::JsonMap *entry = (json::JsonMap *)m_json->GetObject(pszName);
if (entry == NULL) {
// Scenery gobs and cut scene images are "hardcoded" into the levels
// files as .tbm and .rbm. If pszName is a .tbm or .rbm, load as .png
char *pszSuffix = strrchr(pszName, '.');
if (pszSuffix) {
if ((strcmp(pszSuffix, ".tbm") == 0) || (strcmp(pszSuffix, ".rbm") == 0)) {
// Dump the filename, remove the suffix, then append the .png suffix
char *psz = strdup(pszName);
psz[strlen(pszName) - strlen(pszSuffix)] = '\0';
char sz[MAX_PATH];
sprintf(sz, "%s.png", psz);
free(psz);
return CreateTBitmap(sz);
}
}
// Wasnt a .tbm or .rbm, loading failed
LOG() << "couldn't find TBitmap in atlas json: " << pszName;
return NULL;
}
int *anSideMap = new int[kcSides];
if (anSideMap == NULL) {
return NULL;
}
json::JsonArray *atlases = (json::JsonArray *)entry->GetObject("atlases");
for (int i = 0; i < kcSides; i++) {
anSideMap[i] = ((json::JsonNumber *)atlases->GetObject(i))->GetInteger();
}
TBitmap *ptbm = new TBitmap();
Assert(ptbm != NULL, "out of memory!");
if (ptbm == NULL)
return NULL;
if (!ptbm->Init(
pszName,
entry->GetInteger("x"),
entry->GetInteger("y"),
entry->GetInteger("cx"),
entry->GetInteger("cy"),
entry->GetInteger("cx_orig"),
entry->GetInteger("cy_orig"),
entry->GetInteger("cc_left"),
entry->GetInteger("cc_top"),
anSideMap)) {
delete ptbm;
return NULL;
}
return ptbm;
}
} // namespace wi