diff --git a/.gitignore b/.gitignore index c8f49c2..b65c3f4 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,6 @@ editor.png .vs/ *.opendb gfx/ +res/ +*.tmx2gba +map/ diff --git a/inc/XGetopt.h b/inc/XGetopt.h index fa6f6ad..64eb376 100644 --- a/inc/XGetopt.h +++ b/inc/XGetopt.h @@ -15,9 +15,10 @@ #ifndef XGETOPT_H #define XGETOPT_H -extern int optind, opterr; -extern char *optarg; +extern int optind; +extern char *optarg, *next; +void getoptClear (); int getopt(int argc, char *argv[], char *optstring); #endif //XGETOPT_H diff --git a/src/XGetopt.cpp b/src/XGetopt.cpp index f622ebb..092f7c2 100644 --- a/src/XGetopt.cpp +++ b/src/XGetopt.cpp @@ -146,11 +146,18 @@ /////////////////////////////////////////////////////////////////////////////// char *optarg; // global argument pointer +char *next; int optind = 0; // global argv index +void getoptClear () +{ + optarg = nullptr; + next = nullptr; + optind = 0; +} + int getopt(int argc, char *argv[], char *optstring) { - static char *next = nullptr; if (optind == 0) next = nullptr; diff --git a/src/tmx2gba.cpp b/src/tmx2gba.cpp index 424b014..dd42596 100644 --- a/src/tmx2gba.cpp +++ b/src/tmx2gba.cpp @@ -22,47 +22,67 @@ #include "tmxreader.h" #include "tmxlayer.h" +#include "tmxobject.h" #include #include #include #include +#include #include #include #include #include +using std::cout; +using std::cerr; +using std::endl; +using std::string; +using std::vector; +using std::map; +using std::ifstream; +using std::ofstream; +using std::stoi; +using std::min; +using std::max; +using std::ios; -static const std::string g_strUsage = "Usage: tmx2gba [-h] [-r offset] [-lyc name] [-p 0-15] <-i inpath> <-o outpath>\nRun 'tmx2gba -h' to view all available options."; -static const std::string g_strFullHelp = R"(Usage: tmx2gba [-h] [-r offset] [-lyc name] [-p 0-15] <-i inpath> <-o outpath> - --h ---------- Display this help & command info. --l --- Name of layer to use (default first layer in TMX). --y --- Layer for palette mappings. --c --- Output a separate 8bit collision map of the specified layer. --r - Offset tile indices (default 0). --p <0-15> --- Select which palette to use for 4-bit tilesets. --i --- Path to input TMX file. --o --- Path to output files.)"; - +static const string g_strUsage = "Usage: tmx2gba [-h] [-f file] [-r offset] [-lyc name] [-p 0-15] [-m name;id] <-i inpath> <-o outpath>"; +static const string g_strHelpShort = "Run 'tmx2gba -h' to view all available options."; +static const string g_strHelpFull = R"( +-h ------------ Display this help & command info. +-l ----- Name of layer to use (default first layer in TMX). +-y ----- Layer for palette mappings. +-c ----- Output a separate 8bit collision map of the specified layer. +-r --- Offset tile indices (default 0). +-p <0-15> ----- Select which palette to use for 4-bit tilesets. +-m -- Map an object name to an ID, will enable object exports. +-i ----- Path to input TMX file. +-o ----- Path to output files. +-f ----- Specify a file to use for flags, will override any options specified in the cmd line.)"; struct SParams { - std::string inPath, outPath; - std::string layer, collisionlay, paletteLay; + bool help = false; + string inPath, outPath; + string layer, collisionlay, paletteLay; + string flagFile; int offset = 0; int palette = 0; + vector objMappings; + bool objExport = false; }; -bool ParseArgs ( int argc, char** argv, SParams* params ) +void ParseArgs ( int argc, char** argv, SParams* params ) { char cOption; - while ( ( cOption = (char)getopt ( argc, argv, "hr:l:c:p:y:i:o:" ) ) > 0 ) + getoptClear (); + while ( ( cOption = (char)getopt ( argc, argv, "hr:l:c:p:y:m:i:o:f:" ) ) > 0 ) { switch ( cOption ) { case ( 'h' ): - std::cout << g_strFullHelp << std::endl; - return 0; + params->help = true; + return; case ( 'l' ): params->layer = optarg; @@ -77,11 +97,16 @@ bool ParseArgs ( int argc, char** argv, SParams* params ) break; case ( 'r' ): - params->offset = std::stoi ( optarg ); + params->offset = stoi ( optarg ); break; case ( 'p' ): - params->palette = std::stoi ( optarg ); + params->palette = stoi ( optarg ); + break; + + case ( 'm' ): + params->objExport = true; + params->objMappings.push_back ( optarg ); break; case ( 'i' ): @@ -92,28 +117,35 @@ bool ParseArgs ( int argc, char** argv, SParams* params ) params->outPath = optarg; break; + case ( 'f' ): + params->flagFile = optarg; + break; + default: break; } } +} +bool CheckArgs ( const SParams* params ) +{ // Check my paranoia. if ( params->inPath.empty () ) { - std::cerr << "No input file specified." << std::endl; - std::cout << g_strUsage << std::endl; + cerr << "No input file specified." << endl; + cout << g_strUsage << endl << g_strHelpShort << endl; return false; } if ( params->outPath.empty () ) { - std::cerr << "No output file specified." << std::endl; - std::cout << g_strUsage << std::endl; + cerr << "No output file specified." << endl; + cout << g_strUsage << endl << g_strHelpShort << endl; return false; } if ( params->palette < 0 || params->palette > 15 ) { - std::cerr << "Invalid palette index." << std::endl; - std::cout << g_strUsage << std::endl; + cerr << "Invalid palette index." << endl; + cout << g_strUsage << endl << g_strHelpShort << endl; return false; } @@ -122,12 +154,12 @@ bool ParseArgs ( int argc, char** argv, SParams* params ) template -void WriteArray ( std::ofstream& a_fout, const std::vector& a_dat, int a_perCol = 16 ) +void WriteArray ( ofstream& a_fout, const vector& a_dat, int a_perCol = 16 ) { const int w = sizeof(T) * 2; int col = 0; - std::string datType = "ERR"; + string datType = "ERR"; if ( sizeof(T) == 1 ) { datType = ".byte"; @@ -143,8 +175,8 @@ void WriteArray ( std::ofstream& a_fout, const std::vector& a_dat, int a_perC datType = ".word"; } - a_fout.setf ( std::ios::hex, std::ios::basefield ); - a_fout.setf ( std::ios::showbase ); + a_fout.setf ( ios::hex, ios::basefield ); + a_fout.setf ( ios::showbase ); size_t i = 0; for ( T element : a_dat ) @@ -154,7 +186,6 @@ void WriteArray ( std::ofstream& a_fout, const std::vector& a_dat, int a_perC a_fout << "\t" << datType << " "; } - //a_fout << "0x" << std::hex << std::setw ( w ) << std::setfill ( '0' ) << (int)element; a_fout << std::hex << (int)element; if ( i < a_dat.size () - 1 ) @@ -165,7 +196,7 @@ void WriteArray ( std::ofstream& a_fout, const std::vector& a_dat, int a_perC } else { - a_fout << "" << std::endl; + a_fout << "" << endl; col = 0; } } @@ -177,17 +208,119 @@ void WriteArray ( std::ofstream& a_fout, const std::vector& a_dat, int a_perC int main ( int argc, char** argv ) { SParams params; - if ( !ParseArgs ( argc, argv, ¶ms ) ) + ParseArgs ( argc, argv, ¶ms ); + + if ( params.help ) + { + cout << g_strUsage << endl << g_strHelpFull << endl; + return 0; + } + + if ( params.flagFile.length () != 0 ) + { + ifstream paramFile ( params.flagFile ); + if ( !paramFile.is_open () ) + { + cerr << "Failed to open param file." << endl; + return -1; + } + + vector fileArgTokens; + fileArgTokens.push_back ( "auu~~" ); + bool carry = false; + string token; + while ( !paramFile.eof () ) + { + if ( carry ) + { + string tmp; + paramFile >> tmp; + token += " "; + token += tmp; + } + else + { + token.clear (); + paramFile >> token; + } + + if ( token == "" ) + { + continue; + } + + bool qFr = token[0] == '"'; + bool qBk = token[token.length () - 1] == '"'; + if ( qFr && qBk ) + { + fileArgTokens.push_back ( token.substr ( 1, token.length () - 2 ) ); + } + else + if ( qFr ) + { + fileArgTokens.push_back ( token.substr ( 1, token.length () - 1 ) ); + carry = true; + } + else + if ( qBk ) + { + fileArgTokens.push_back ( token.substr ( 0, token.length () - 1 ) ); + carry = false; + } + else + { + fileArgTokens.push_back ( token ); + } + } + + vector fileArgs; + fileArgs.reserve ( fileArgTokens.size () ); + for ( auto& token : fileArgTokens ) + { + fileArgs.push_back ( token.c_str () ); + } + + ParseArgs ( fileArgs.size (), (char**)fileArgs.data (), ¶ms ); + } + + if ( !CheckArgs ( ¶ms ) ) { return -1; } + // Object mappings. + map objMapping; + if ( params.objExport ) + { + for ( auto token : params.objMappings ) + { + int splitter = token.find_last_of ( ';' ); + if ( splitter == -1 ) + { + cerr << "Malformed mapping (missing a splitter)." << endl; + return -1; + } + + try + { + string name = token.substr ( 0, splitter ); + int id = stoi ( token.substr ( splitter + 1 ) ); + + objMapping[name] = id; + } + catch ( std::exception ) + { + cerr << "Malformed mapping, make sure id is numeric." << endl; + } + } + } + // Open & read input file. CTmxReader tmx; - std::ifstream fin ( params.inPath ); + ifstream fin ( params.inPath ); if ( !fin.is_open () ) { - std::cerr << "Failed to open input file." << std::endl; + cerr << "Failed to open input file." << endl; return -1; } tmx.Open ( fin ); @@ -195,7 +328,7 @@ int main ( int argc, char** argv ) // Get layers. if ( tmx.GetLayerCount () == 0 ) { - std::cerr << "No layers found." << std::endl; + cerr << "No layers found." << endl; return -1; } const CTmxLayer* pLayerGfx = params.layer.empty () ? tmx.GetLayer ( 0 ) : tmx.GetLayer ( params.layer ); @@ -204,46 +337,46 @@ int main ( int argc, char** argv ) if ( pLayerGfx == nullptr ) { - std::cerr << "Input layer not found." << std::endl; + cerr << "Input layer not found." << endl; return -1; } // Open output files. - std::ofstream foutS ( params.outPath + ".s", std::ios::binary ); - std::ofstream foutH ( params.outPath + ".h", std::ios::binary ); + ofstream foutS ( params.outPath + ".s" ); + ofstream foutH ( params.outPath + ".h" ); if ( !foutS.is_open () || !foutH.is_open () ) { - std::cerr << "Failed to create output file(s)."; + cerr << "Failed to create output file(s)."; return -1; } - int slashPos = std::max ( (int)params.outPath.find_last_of ( '/' ), (int)params.outPath.find_last_of ( '\\' ) ); - std::string name = params.outPath; + int slashPos = max ( (int)params.outPath.find_last_of ( '/' ), (int)params.outPath.find_last_of ( '\\' ) ); + string name = params.outPath; if ( slashPos != -1 ) { name = name.substr ( slashPos + 1 ); } // Write header guards. - std::string guard = "__TMX2GBA_" + name + "__"; + string guard = "__TMX2GBA_" + name + "__"; for ( auto& c: guard ) c = (char)toupper ( (int)c ); - foutH << "#ifndef " << guard << std::endl; - foutH << "#define " << guard << std::endl; - foutH << std::endl; - foutH << "#define " << name << "Width " << tmx.GetWidth () << std::endl; - foutH << "#define " << name << "Height " << tmx.GetHeight () << std::endl; - foutH << std::endl; + foutH << "#ifndef " << guard << endl; + foutH << "#define " << guard << endl; + foutH << endl; + foutH << "#define " << name << "Width " << tmx.GetWidth () << endl; + foutH << "#define " << name << "Height " << tmx.GetHeight () << endl; + foutH << endl; // Convert to GBA-friendly charmap data. const uint32_t* pRead = pLayerGfx->GetData (); const uint32_t* pPalRead = pLayerPal == nullptr ? nullptr : pLayerPal->GetData (); - std::vector vucCharDat; + vector vucCharDat; vucCharDat.reserve ( pLayerGfx->GetWidth () * pLayerGfx->GetHeight () ); for ( size_t i = 0; i < size_t(pLayerGfx->GetWidth () * pLayerGfx->GetHeight ()); ++i ) { uint32_t uiRead = (*pRead++); - uint16_t usTile = (uint16_t)std::max ( 0, tmx.LidFromGid ( uiRead & ~FLIP_MASK ) + params.offset ); + uint16_t usTile = (uint16_t)max ( 0, tmx.LidFromGid ( uiRead & ~FLIP_MASK ) + params.offset ); uint8_t ucFlags = 0x0; // Get flipped! @@ -266,36 +399,25 @@ int main ( int argc, char** argv ) } // Save out charmap. - foutH << "#define " << name << "TilesLen " << vucCharDat.size () * 2 << std::endl; - foutH << "extern const unsigned short " << name << "Tiles[" << vucCharDat.size () << "];" << std::endl; - foutH << std::endl; + foutH << "#define " << name << "TilesLen " << vucCharDat.size () * 2 << endl; + foutH << "extern const unsigned short " << name << "Tiles[" << vucCharDat.size () << "];" << endl; + foutH << endl; - foutS << "\t.section .rodata" << std::endl; - foutS << "\t.align 2" << std::endl; - foutS << "\t.global " << name << "Tiles" << std::endl; - foutS << "\t.hidden " << name << "Tiles" << std::endl; - foutS << name << "Tiles" << ":" << std::endl; + foutS << "\t.section .rodata" << endl; + foutS << "\t.align 2" << endl; + foutS << "\t.global " << name << "Tiles" << endl; + foutS << "\t.hidden " << name << "Tiles" << endl; + foutS << name << "Tiles" << ":" << endl; WriteArray ( foutS, vucCharDat ); - foutS << std::endl; - - /* - std::ofstream fout ( params.outPath, std::ios::binary ); - if ( !fout.is_open () ) - { - std::cerr << "Failed to create output file."; - return -1; - } - fout.write ( (const char*)vucCharDat.data (), vucCharDat.size () * sizeof(uint16_t) ); - fout.close (); - */ + foutS << endl; // Convert collision map & save it out. if ( pLayerCls != nullptr ) { - std::vector vucCollisionDat; + vector vucCollisionDat; vucCollisionDat.reserve ( pLayerCls->GetWidth () * pLayerCls->GetHeight () ); - const uint32_t* pRead = pLayerCls->GetData (); + pRead = pLayerCls->GetData (); for ( int i = 0; i < pLayerCls->GetWidth () * pLayerCls->GetHeight (); ++i ) { uint8_t ucTile = (uint8_t)tmx.LidFromGid ( (*pRead++) & ~FLIP_MASK ); @@ -303,9 +425,9 @@ int main ( int argc, char** argv ) } // Try to nicely append "_collision" to the output name. - std::string strPath; + string strPath; size_t extPos = params.outPath.find_last_of ( '.' ); - if ( extPos != std::string::npos ) + if ( extPos != string::npos ) { strPath = params.outPath.insert ( extPos, "_collision" ); } @@ -315,30 +437,56 @@ int main ( int argc, char** argv ) } // Save it out. - foutH << "#define " << name << "CollisionLen " << vucCollisionDat.size () << std::endl; - foutH << "extern const unsigned char " << name << "Collision[" << vucCollisionDat.size () << "];" << std::endl; - foutH << std::endl; + foutH << "#define " << name << "CollisionLen " << vucCollisionDat.size () << endl; + foutH << "extern const unsigned char " << name << "Collision[" << vucCollisionDat.size () << "];" << endl; + foutH << endl; - foutS << std::endl; - foutS << "\t.section .rodata" << std::endl; - foutS << "\t.align 2" << std::endl; - foutS << "\t.global " << name << "Collision" << std::endl; - foutS << "\t.hidden " << name << "Collision" << std::endl; - foutS << name << "Collision" << ":" << std::endl; + foutS << endl; + foutS << "\t.section .rodata" << endl; + foutS << "\t.align 2" << endl; + foutS << "\t.global " << name << "Collision" << endl; + foutS << "\t.hidden " << name << "Collision" << endl; + foutS << name << "Collision" << ":" << endl; WriteArray ( foutS, vucCollisionDat ); - foutS << std::endl; - - /* - fout.open ( strPath, std::ios::binary ); - if ( fout.is_open () ) - { - fout.write ( (const char*)vucCollisionDat.data (), vucCollisionDat.size () * sizeof(uint8_t) ); - fout.close (); - } - */ + foutS << endl; } - foutH << "#endif//" << guard << std::endl; + if ( params.objExport ) + { + vector objDat; + for ( int i = 0; i < tmx.GetObjectCount (); ++i ) + { + auto obj = tmx.GetObject ( i ); + auto it = objMapping.find ( obj->GetName () ); + if ( it == objMapping.end () ) + { + continue; + } + + float x, y; + obj->GetPos ( &x, &y ); + objDat.push_back ( it->second ); + objDat.push_back ( (int)( x * 256.0f ) ); + objDat.push_back ( (int)( y * 256.0f ) ); + } + + // Save it out. + foutH << "#define " << name << "ObjCount " << objDat.size () / 3 << endl; + foutH << "#define " << name << "ObjdatLen " << objDat.size () * sizeof(int) << endl; + foutH << "extern const unsigned int " << name << "Objdat[" << objDat.size () << "];" << endl; + foutH << endl; + + foutS << endl; + foutS << "\t.section .rodata" << endl; + foutS << "\t.align 2" << endl; + foutS << "\t.global " << name << "Objdat" << endl; + foutS << "\t.hidden " << name << "Objdat" << endl; + foutS << name << "Objdat" << ":" << endl; + WriteArray ( foutS, objDat ); + foutS << endl; + } + + foutH << "#endif//" << guard << endl; foutH.close (); foutS.close (); diff --git a/src/tmxobject.cpp b/src/tmxobject.cpp new file mode 100644 index 0000000..32b2cc1 --- /dev/null +++ b/src/tmxobject.cpp @@ -0,0 +1,61 @@ +/* tmxobject.cpp + + Copyright (C) 2015 Nicholas Curtis + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + +*/ + +#include "tmxobject.h" + +CTmxObject::CTmxObject () : + m_name ( "" ), + m_x ( 0.0f ), m_y ( 0.0f ) +{ + +} + +CTmxObject::CTmxObject ( const std::string& a_name, float a_x, float a_y ) : + m_name ( a_name ), + m_x ( a_x ), m_y ( a_y ) +{ + +} + +CTmxObject::~CTmxObject () +{ + +} + + +const std::string& CTmxObject::GetName () const +{ + return m_name; +} + +void CTmxObject::GetPos ( float* a_outX, float* a_outY ) const +{ + if ( a_outX != nullptr ) + { + *a_outX = m_x; + } + if ( a_outY != nullptr ) + { + *a_outY = m_y; + } +} + diff --git a/src/tmxobject.h b/src/tmxobject.h new file mode 100644 index 0000000..9ce2131 --- /dev/null +++ b/src/tmxobject.h @@ -0,0 +1,21 @@ +#ifndef __TMXOBJECT_H__ +#define __TMXOBJECT_H__ + +#include + +class CTmxObject +{ +public: + CTmxObject (); + CTmxObject ( const std::string& a_name, float a_x, float a_y ); + ~CTmxObject (); + + const std::string& GetName () const; + void GetPos ( float* a_outX, float* a_outY ) const; + +private: + std::string m_name; + float m_x, m_y; +}; + +#endif//__TMXOBJECT_H__ diff --git a/src/tmxreader.cpp b/src/tmxreader.cpp index 8ea4bcb..43d0920 100644 --- a/src/tmxreader.cpp +++ b/src/tmxreader.cpp @@ -22,6 +22,7 @@ #include "tmxreader.h" #include "tmxtileset.h" +#include "tmxobject.h" #include "tmxlayer.h" #include #include @@ -39,18 +40,18 @@ CTmxReader::CTmxReader () CTmxReader::~CTmxReader () { // Delete old tilesets. - for ( auto pTileset : m_vpTileset ) + for ( auto pTileset : m_tileset ) { delete pTileset; } - m_vpTileset.clear (); + m_tileset.clear (); // Delete old layers. - for ( auto pLay : m_vpLayers ) + for ( auto pLay : m_layers ) { delete pLay; } - m_vpLayers.clear (); + m_layers.clear (); } @@ -104,7 +105,7 @@ void CTmxReader::ReadTileset ( rapidxml::xml_node<>* a_xNode ) uiFirstGid = std::stoul ( xAttrib->value () ); } - m_vpTileset.push_back ( new CTmxTileset ( szName, szSource, uiFirstGid ) ); + m_tileset.push_back ( new CTmxTileset ( szName, szSource, uiFirstGid ) ); } void CTmxReader::ReadLayer ( rapidxml::xml_node<>* a_xNode ) @@ -149,26 +150,65 @@ void CTmxReader::ReadLayer ( rapidxml::xml_node<>* a_xNode ) } } - m_vpLayers.push_back ( new CTmxLayer ( iWidth, iHeight, szName, pTileDat ) ); + m_layers.push_back ( new CTmxLayer ( iWidth, iHeight, szName, pTileDat ) ); +} + +void CTmxReader::ReadObjects ( rapidxml::xml_node<>* a_xNode ) +{ + for ( auto xNode = a_xNode->first_node (); xNode != nullptr; xNode = xNode->next_sibling () ) + { + if ( strcmp ( xNode->name (), "object" ) != 0 ) + { + continue; + } + + rapidxml::xml_attribute<>* xAttrib; + const char* name = ""; + float x = 0.0f; + float y = 0.0f; + + // Read name. + xAttrib = xNode->first_attribute ( "name" ); + if ( xAttrib != nullptr ) + { + name = xAttrib->value (); + } + + // Read X pos. + xAttrib = xNode->first_attribute ( "x" ); + if ( xAttrib != nullptr ) + { + x = std::stof ( xAttrib->value () ); + } + + // Read Y pos. + xAttrib = xNode->first_attribute ( "y" ); + if ( xAttrib != nullptr ) + { + y = std::stof ( xAttrib->value () ); + } + + m_objects.push_back ( new CTmxObject ( name, x, y ) ); + } } void CTmxReader::Open ( std::istream& a_in ) { // Delete old tilesets. - for ( auto pTileset : m_vpTileset ) + for ( auto pTileset : m_tileset ) { delete pTileset; } - m_vpTileset.clear (); + m_tileset.clear (); // Delete old layers. - for ( auto pLay : m_vpLayers ) + for ( auto pLay : m_layers ) { delete pLay; } - m_vpLayers.clear (); + m_layers.clear (); - m_vuiGidTable.clear (); + m_gidTable.clear (); // Read string into a buffer. std::stringstream buf; @@ -191,11 +231,11 @@ void CTmxReader::Open ( std::istream& a_in ) rapidxml::xml_attribute<>* xAttrib = nullptr; if ( ( xAttrib = xMap->first_attribute ( "width" ) ) != nullptr ) { - m_iWidth = std::stoi ( xAttrib->value () ); + m_width = std::stoi ( xAttrib->value () ); } if ( ( xAttrib = xMap->first_attribute ( "height" ) ) != nullptr ) { - m_iHeight = std::stoi ( xAttrib->value () ); + m_height = std::stoi ( xAttrib->value () ); } // Read nodes. @@ -211,36 +251,41 @@ void CTmxReader::Open ( std::istream& a_in ) { ReadTileset ( xNode ); } + else + if ( strcmp ( xNode->name (), "objectgroup" ) == 0 ) + { + ReadObjects ( xNode ); + } } // Generate global id table. - for ( auto pTileset : m_vpTileset ) + for ( auto pTileset : m_tileset ) { - m_vuiGidTable.push_back ( pTileset->GetFirstGid () ); + m_gidTable.push_back ( pTileset->GetFirstGid () ); } - std::sort ( m_vuiGidTable.rbegin (), m_vuiGidTable.rend () ); + std::sort ( m_gidTable.rbegin (), m_gidTable.rend () ); } int CTmxReader::GetWidth () const { - return m_iWidth; + return m_width; } int CTmxReader::GetHeight () const { - return m_iHeight; + return m_height; } -const CTmxLayer* CTmxReader::GetLayer ( int a_iId ) const +const CTmxLayer* CTmxReader::GetLayer ( int a_id ) const { - return m_vpLayers[a_iId]; + return m_layers[a_id]; } const CTmxLayer* CTmxReader::GetLayer ( std::string a_strName ) const { - for ( auto pLay : m_vpLayers ) + for ( auto pLay : m_layers ) { if ( pLay->GetName ().compare ( a_strName ) == 0 ) { @@ -253,13 +298,24 @@ const CTmxLayer* CTmxReader::GetLayer ( std::string a_strName ) const int CTmxReader::GetLayerCount () const { - return m_vpLayers.size (); + return m_layers.size (); +} + + +const CTmxObject* CTmxReader::GetObject ( int a_id ) const +{ + return m_objects[a_id]; +} + +int CTmxReader::GetObjectCount () const +{ + return m_objects.size (); } uint32_t CTmxReader::LidFromGid ( uint32_t a_uiGid ) { - for ( uint32_t uiFirst : m_vuiGidTable ) + for ( uint32_t uiFirst : m_gidTable ) { if ( uiFirst <= a_uiGid ) { diff --git a/src/tmxreader.h b/src/tmxreader.h index fdaa110..5054695 100644 --- a/src/tmxreader.h +++ b/src/tmxreader.h @@ -8,6 +8,7 @@ class CTmxTileset; class CTmxLayer; +class CTmxObject; namespace rapidxml { template class xml_node; } class CTmxReader @@ -21,21 +22,26 @@ public: int GetWidth () const; int GetHeight () const; - const CTmxLayer* GetLayer ( int a_iId ) const; + const CTmxLayer* GetLayer ( int a_id ) const; const CTmxLayer* GetLayer ( std::string a_strName ) const; int GetLayerCount () const; - uint32_t LidFromGid ( uint32_t a_uiGid ); + const CTmxObject* GetObject ( int a_id ) const; + int GetObjectCount () const; + + uint32_t LidFromGid ( uint32_t a_gid ); private: - bool DecodeMap ( uint32_t* a_pOut, size_t a_outSize, const std::string& a_strIn ); + bool DecodeMap ( uint32_t* a_out, size_t a_outSize, const std::string& a_strIn ); void ReadTileset ( rapidxml::xml_node<>* a_xNode ); void ReadLayer ( rapidxml::xml_node<>* a_xNode ); + void ReadObjects ( rapidxml::xml_node<>* a_xNode ); - int m_iWidth, m_iHeight; - std::vector m_vpTileset; - std::vector m_vpLayers; - std::vector m_vuiGidTable; + int m_width, m_height; + std::vector m_tileset; + std::vector m_layers; + std::vector m_objects; + std::vector m_gidTable; }; diff --git a/tmx2gba.vcxproj b/tmx2gba.vcxproj index fc5fe4f..985fd4e 100644 --- a/tmx2gba.vcxproj +++ b/tmx2gba.vcxproj @@ -69,6 +69,7 @@ + @@ -82,6 +83,7 @@ + diff --git a/tmx2gba.vcxproj.filters b/tmx2gba.vcxproj.filters index b2be5db..a54aa2f 100644 --- a/tmx2gba.vcxproj.filters +++ b/tmx2gba.vcxproj.filters @@ -33,6 +33,9 @@ Source Files + + Source Files + @@ -65,5 +68,8 @@ Header Files + + Header Files + \ No newline at end of file