mirror of
https://github.com/spiffcode/hostile-takeover.git
synced 2026-04-24 19:55:11 -06:00
Add texture atlas manager
This commit is contained in:
parent
901a201a45
commit
97a84b8e27
@ -71,6 +71,7 @@ int gcSupportGobsLimit;
|
||||
bool gfMultiplayer;
|
||||
bool gfIgnoreBluetoothWarning;
|
||||
SpriteManager *gpsprm;
|
||||
TexAtlasMgr *gptam;
|
||||
|
||||
#ifdef STRESS
|
||||
bool gfStress = false;
|
||||
@ -325,6 +326,10 @@ bool Game::Init(int imm)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!InitTexAtlasMgr()) {
|
||||
HostOutputDebugString("Failed to initilize texture atlas manager");
|
||||
}
|
||||
|
||||
// Init memory manager *after* setting screen mode so we know how much dyn ram is left after
|
||||
// allocating back buffers (potentially from main memory).
|
||||
|
||||
@ -635,6 +640,19 @@ bool Game::LoadGameData()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Game::InitTexAtlasMgr()
|
||||
{
|
||||
gptam = new TexAtlasMgr();
|
||||
Assert(gptam != NULL, "out of memory!");
|
||||
if (gptam == NULL)
|
||||
return false;
|
||||
if (!gptam->Init()) {
|
||||
delete gptam;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Game::InitCoordMappingTables()
|
||||
{
|
||||
// Initialize world -> pixel coord mapping table
|
||||
@ -2037,6 +2055,9 @@ void Game::Exit()
|
||||
delete gpstrtbl;
|
||||
gpstrtbl = NULL;
|
||||
|
||||
delete gptam;
|
||||
gptam = NULL;
|
||||
|
||||
// Pop off all data files
|
||||
|
||||
while (gpakr.Pop())
|
||||
|
||||
21
game/ht.h
21
game/ht.h
@ -265,6 +265,7 @@ typedef word CacheHandle; // hc
|
||||
#define secBuilderGob secCode12
|
||||
#define secDrm secCode16
|
||||
#define secBtTransport secCode17
|
||||
#define secTexAtlasMgr secCode13
|
||||
|
||||
// Performance options
|
||||
|
||||
@ -1162,6 +1163,24 @@ private:
|
||||
};
|
||||
TBitmap *CreateTBitmap(char *pszName) secTBitmap;
|
||||
|
||||
// Texture Atlas Manager
|
||||
|
||||
class TexAtlasMgr
|
||||
{
|
||||
public:
|
||||
TexAtlasMgr() secTexAtlasMgr;
|
||||
~TexAtlasMgr() secTexAtlasMgr;
|
||||
|
||||
bool Init() secTexAtlasMgr;
|
||||
TBitmap *CreateTBitmap(char *pszName) secTexAtlasMgr;
|
||||
void BltTo(TBitmap *ptbmSrc, DibBitmap *pbmDst, int xDst, int yDst, Side side, Rect *prcSrc) secTexAtlasMgr;
|
||||
|
||||
private:
|
||||
int m_natlases;
|
||||
json::JsonMap *m_json;
|
||||
DibBitmap **m_pbmAtlases;
|
||||
};
|
||||
|
||||
struct FontHeader // fnth
|
||||
{
|
||||
word cy;
|
||||
@ -2354,6 +2373,7 @@ private:
|
||||
int FindBestModeMatch(int nSizeDataAbove) secGame;
|
||||
void AddModeMatches(int nDepthData, int nSizeData, int nDepthOrGreater, int cxWidthOrGreater) secGame;
|
||||
bool LoadGameData() secGame;
|
||||
bool InitTexAtlasMgr() secGame;
|
||||
bool InitCoordMappingTables() secGame;
|
||||
bool InitSimulation(Stream *pstm, char *pszLevel, word wfRole,
|
||||
dword gameid, Chatter *chatter);
|
||||
@ -8541,6 +8561,7 @@ extern int gnMPPos;
|
||||
#endif
|
||||
extern char *gpszDataDir;
|
||||
extern bool gfIgnoreBluetoothWarning;
|
||||
extern TexAtlasMgr *gptam;
|
||||
|
||||
inline Color GetColor(int iclr) {
|
||||
return gaclrFixed[iclr];
|
||||
|
||||
194
game/texatlasmgr.cpp
Normal file
194
game/texatlasmgr.cpp
Normal file
@ -0,0 +1,194 @@
|
||||
#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
|
||||
Loading…
Reference in New Issue
Block a user