mirror of
https://github.com/ScrelliCopter/tmx2gba.git
synced 2025-02-21 03:29:25 +11:00
refactor
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
/* tmxreader.cpp
|
||||
|
||||
Copyright (C) 2015 a dinosaur
|
||||
Copyright (C) 2015-2022 a dinosaur
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -20,10 +20,10 @@
|
||||
|
||||
*/
|
||||
|
||||
#include "tmxreader.h"
|
||||
#include "tmxtileset.h"
|
||||
#include "tmxobject.h"
|
||||
#include "tmxlayer.h"
|
||||
#include "tmxreader.hpp"
|
||||
#include "tmxtileset.hpp"
|
||||
#include "tmxobject.hpp"
|
||||
#include "tmxlayer.hpp"
|
||||
#include <cstdint>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
@@ -32,296 +32,208 @@
|
||||
#include <miniz.h>
|
||||
|
||||
|
||||
CTmxReader::CTmxReader ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CTmxReader::~CTmxReader ()
|
||||
TmxReader::~TmxReader()
|
||||
{
|
||||
// Delete old tilesets.
|
||||
for ( auto pTileset : m_tileset )
|
||||
{
|
||||
for (auto pTileset : mTilesets)
|
||||
delete pTileset;
|
||||
}
|
||||
m_tileset.clear ();
|
||||
mTilesets.clear();
|
||||
|
||||
// Delete old layers.
|
||||
for ( auto pLay : m_layers )
|
||||
{
|
||||
for (auto pLay : mLayers)
|
||||
delete pLay;
|
||||
}
|
||||
m_layers.clear ();
|
||||
mLayers.clear();
|
||||
}
|
||||
|
||||
|
||||
bool CTmxReader::DecodeMap ( uint32_t* a_pOut, size_t a_outSize, const std::string& a_strIn )
|
||||
bool TmxReader::DecodeMap(uint32_t* aOut, size_t aOutSize, const std::string& aStrIn)
|
||||
{
|
||||
// Decode base64 string.
|
||||
size_t cutTheCrap = a_strIn.find_first_not_of ( " \t\n\r" );
|
||||
std::string strDec = base64_decode ( a_strIn.substr ( cutTheCrap ) );
|
||||
size_t cutTheCrap = aStrIn.find_first_not_of(" \t\n\r");
|
||||
std::string decoded = base64_decode(aStrIn.substr(cutTheCrap));
|
||||
|
||||
// Decompress compressed data.
|
||||
mz_ulong uiDstSize = a_outSize;
|
||||
int iRes = uncompress (
|
||||
(unsigned char*)a_pOut, &uiDstSize,
|
||||
(const unsigned char*)strDec.data (), strDec.size ()
|
||||
);
|
||||
strDec.clear ();
|
||||
if ( iRes < 0 )
|
||||
{
|
||||
auto dstSize = static_cast<mz_ulong>(aOutSize);
|
||||
int res = uncompress(
|
||||
(unsigned char*)aOut,
|
||||
&dstSize,
|
||||
reinterpret_cast<const unsigned char*>(decoded.data()),
|
||||
static_cast<mz_ulong>(decoded.size()));
|
||||
decoded.clear();
|
||||
if (res < 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CTmxReader::ReadTileset ( rapidxml::xml_node<>* a_xNode )
|
||||
void TmxReader::ReadTileset(rapidxml::xml_node<>* aXNode)
|
||||
{
|
||||
rapidxml::xml_attribute<>* xAttrib;
|
||||
|
||||
const char* szName = "";
|
||||
const char* szSource = "";
|
||||
uint32_t uiFirstGid = 0;
|
||||
const char* name = "";
|
||||
const char* source = "";
|
||||
uint32_t firstGid = 0;
|
||||
|
||||
// Read name.
|
||||
xAttrib = a_xNode->first_attribute ( "name" );
|
||||
if ( xAttrib != nullptr )
|
||||
{
|
||||
szName = xAttrib->value ();
|
||||
}
|
||||
xAttrib = aXNode->first_attribute("name");
|
||||
if (xAttrib != nullptr)
|
||||
name = xAttrib->value();
|
||||
|
||||
// Read source.
|
||||
xAttrib = a_xNode->first_attribute ( "source" );
|
||||
if ( xAttrib != nullptr )
|
||||
{
|
||||
szSource = xAttrib->value ();
|
||||
}
|
||||
xAttrib = aXNode->first_attribute("source");
|
||||
if (xAttrib != nullptr)
|
||||
source = xAttrib->value();
|
||||
|
||||
// Read first global ID.
|
||||
xAttrib = a_xNode->first_attribute ( "firstgid" );
|
||||
if ( xAttrib != nullptr )
|
||||
{
|
||||
uiFirstGid = std::stoul ( xAttrib->value () );
|
||||
}
|
||||
xAttrib = aXNode->first_attribute("firstgid");
|
||||
if (xAttrib != nullptr)
|
||||
firstGid = std::stoul(xAttrib->value());
|
||||
|
||||
m_tileset.push_back ( new CTmxTileset ( szName, szSource, uiFirstGid ) );
|
||||
mTilesets.push_back(new TmxTileset(name, source, firstGid));
|
||||
}
|
||||
|
||||
void CTmxReader::ReadLayer ( rapidxml::xml_node<>* a_xNode )
|
||||
void TmxReader::ReadLayer(rapidxml::xml_node<>* aXNode)
|
||||
{
|
||||
rapidxml::xml_attribute<>* xAttrib;
|
||||
const char* szName = "";
|
||||
int iWidth = 0;
|
||||
int iHeight = 0;
|
||||
uint32_t* pTileDat = nullptr;
|
||||
const char* name = "";
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
uint32_t* tileDat = nullptr;
|
||||
|
||||
// Read name.
|
||||
xAttrib = a_xNode->first_attribute ( "name" );
|
||||
if ( xAttrib != nullptr )
|
||||
{
|
||||
szName = xAttrib->value ();
|
||||
}
|
||||
xAttrib = aXNode->first_attribute("name");
|
||||
if (xAttrib != nullptr)
|
||||
name = xAttrib->value();
|
||||
|
||||
// Read width.
|
||||
xAttrib = a_xNode->first_attribute ( "width" );
|
||||
if ( xAttrib != nullptr )
|
||||
{
|
||||
iWidth = std::stoi ( xAttrib->value () );
|
||||
}
|
||||
xAttrib = aXNode->first_attribute("width");
|
||||
if (xAttrib != nullptr)
|
||||
width = std::stoi(xAttrib->value());
|
||||
|
||||
// Read height.
|
||||
xAttrib = a_xNode->first_attribute ( "height" );
|
||||
if ( xAttrib != nullptr )
|
||||
{
|
||||
iHeight = std::stoi ( xAttrib->value () );
|
||||
}
|
||||
xAttrib = aXNode->first_attribute("height");
|
||||
if (xAttrib != nullptr)
|
||||
height = std::stoi(xAttrib->value());
|
||||
|
||||
// Read tile data.
|
||||
auto xData = a_xNode->first_node ( "data" );
|
||||
if ( xData != nullptr )
|
||||
auto xData = aXNode->first_node("data");
|
||||
if (xData != nullptr)
|
||||
{
|
||||
// TODO: don't assume base64 & zlib.
|
||||
pTileDat = new uint32_t[iWidth * iHeight];
|
||||
if ( !DecodeMap ( pTileDat, iWidth * iHeight * sizeof(uint32_t), std::string ( xData->value () ) ) )
|
||||
tileDat = new uint32_t[width * height];
|
||||
if (!DecodeMap(tileDat, width * height * sizeof(uint32_t), std::string(xData->value())))
|
||||
{
|
||||
delete[] pTileDat;
|
||||
pTileDat = nullptr;
|
||||
delete[] tileDat;
|
||||
tileDat = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
m_layers.push_back ( new CTmxLayer ( iWidth, iHeight, szName, pTileDat ) );
|
||||
mLayers.push_back(new TmxLayer(width, height, name, tileDat));
|
||||
}
|
||||
|
||||
void CTmxReader::ReadObjects ( rapidxml::xml_node<>* a_xNode )
|
||||
void TmxReader::ReadObjects(rapidxml::xml_node<>* aXNode)
|
||||
{
|
||||
for ( auto xNode = a_xNode->first_node (); xNode != nullptr; xNode = xNode->next_sibling () )
|
||||
for (auto xNode = aXNode->first_node(); xNode != nullptr; xNode = xNode->next_sibling())
|
||||
{
|
||||
if ( strcmp ( xNode->name (), "object" ) != 0 )
|
||||
{
|
||||
if (strcmp(xNode->name(), "object") != 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
rapidxml::xml_attribute<>* xAttrib;
|
||||
const char* name = "";
|
||||
float x = 0.0f;
|
||||
float y = 0.0f;
|
||||
const char* name = "";
|
||||
float x = 0.0f;
|
||||
float y = 0.0f;
|
||||
|
||||
// Read name.
|
||||
xAttrib = xNode->first_attribute ( "name" );
|
||||
if ( xAttrib != nullptr )
|
||||
{
|
||||
name = xAttrib->value ();
|
||||
}
|
||||
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 () );
|
||||
}
|
||||
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 () );
|
||||
}
|
||||
xAttrib = xNode->first_attribute("y");
|
||||
if (xAttrib != nullptr)
|
||||
y = std::stof(xAttrib->value());
|
||||
|
||||
m_objects.push_back ( new CTmxObject ( name, x, y ) );
|
||||
mObjects.push_back(new TmxObject(name, x, y));
|
||||
}
|
||||
}
|
||||
|
||||
void CTmxReader::Open ( std::istream& a_in )
|
||||
void TmxReader::Open(std::istream& aIn)
|
||||
{
|
||||
// Delete old tilesets.
|
||||
for ( auto pTileset : m_tileset )
|
||||
{
|
||||
delete pTileset;
|
||||
}
|
||||
m_tileset.clear ();
|
||||
for (auto tileset : mTilesets)
|
||||
delete tileset;
|
||||
mTilesets.clear();
|
||||
|
||||
// Delete old layers.
|
||||
for ( auto pLay : m_layers )
|
||||
{
|
||||
delete pLay;
|
||||
}
|
||||
m_layers.clear ();
|
||||
for (auto layer : mLayers)
|
||||
delete layer;
|
||||
mLayers.clear();
|
||||
|
||||
m_gidTable.clear ();
|
||||
mGidTable.clear();
|
||||
|
||||
// Read string into a buffer.
|
||||
std::stringstream buf;
|
||||
buf << a_in.rdbuf ();
|
||||
std::string strXml = buf.str ();
|
||||
buf.clear ();
|
||||
buf << aIn.rdbuf();
|
||||
std::string strXml = buf.str();
|
||||
buf.clear();
|
||||
|
||||
// Parse document.
|
||||
rapidxml::xml_document<> xDoc;
|
||||
xDoc.parse<0> ( (char*)strXml.c_str () );
|
||||
xDoc.parse<0>((char*)strXml.c_str());
|
||||
|
||||
// Get map node.
|
||||
auto xMap = xDoc.first_node ( "map" );
|
||||
if ( xMap == nullptr )
|
||||
{
|
||||
auto xMap = xDoc.first_node("map");
|
||||
if (xMap == nullptr)
|
||||
return;
|
||||
}
|
||||
|
||||
// Read map attribs.
|
||||
rapidxml::xml_attribute<>* xAttrib = nullptr;
|
||||
if ( ( xAttrib = xMap->first_attribute ( "width" ) ) != nullptr )
|
||||
{
|
||||
m_width = std::stoi ( xAttrib->value () );
|
||||
}
|
||||
if ( ( xAttrib = xMap->first_attribute ( "height" ) ) != nullptr )
|
||||
{
|
||||
m_height = std::stoi ( xAttrib->value () );
|
||||
}
|
||||
if ((xAttrib = xMap->first_attribute("width")) != nullptr)
|
||||
mWidth = std::stoi(xAttrib->value());
|
||||
if ((xAttrib = xMap->first_attribute("height")) != nullptr)
|
||||
mHeight = std::stoi(xAttrib->value());
|
||||
|
||||
// Read nodes.
|
||||
for ( auto xNode = xMap->first_node (); xNode != nullptr; xNode = xNode->next_sibling () )
|
||||
for (auto xNode = xMap->first_node(); xNode != nullptr; xNode = xNode->next_sibling())
|
||||
{
|
||||
// Read layer nodes.
|
||||
if ( strcmp ( xNode->name (), "layer" ) == 0 )
|
||||
{
|
||||
ReadLayer ( xNode );
|
||||
}
|
||||
if (strcmp(xNode->name(), "layer") == 0)
|
||||
ReadLayer(xNode);
|
||||
else
|
||||
if ( strcmp ( xNode->name (), "tileset" ) == 0 )
|
||||
{
|
||||
ReadTileset ( xNode );
|
||||
}
|
||||
if (strcmp(xNode->name(), "tileset") == 0)
|
||||
ReadTileset(xNode);
|
||||
else
|
||||
if ( strcmp ( xNode->name (), "objectgroup" ) == 0 )
|
||||
{
|
||||
ReadObjects ( xNode );
|
||||
}
|
||||
if (strcmp(xNode->name(), "objectgroup") == 0)
|
||||
ReadObjects(xNode);
|
||||
}
|
||||
|
||||
// Generate global id table.
|
||||
for ( auto pTileset : m_tileset )
|
||||
for (auto tileset : mTilesets)
|
||||
mGidTable.push_back(tileset->GetFirstGid());
|
||||
std::sort(mGidTable.rbegin(), mGidTable.rend());
|
||||
}
|
||||
|
||||
const TmxLayer* TmxReader::GetLayer(const std::string& aName) const
|
||||
{
|
||||
for (auto layer : mLayers)
|
||||
{
|
||||
m_gidTable.push_back ( pTileset->GetFirstGid () );
|
||||
if (layer->GetName() == aName)
|
||||
return layer;
|
||||
}
|
||||
std::sort ( m_gidTable.rbegin (), m_gidTable.rend () );
|
||||
}
|
||||
|
||||
|
||||
int CTmxReader::GetWidth () const
|
||||
{
|
||||
return m_width;
|
||||
}
|
||||
|
||||
int CTmxReader::GetHeight () const
|
||||
{
|
||||
return m_height;
|
||||
}
|
||||
|
||||
|
||||
const CTmxLayer* CTmxReader::GetLayer ( int a_id ) const
|
||||
{
|
||||
return m_layers[a_id];
|
||||
}
|
||||
|
||||
const CTmxLayer* CTmxReader::GetLayer ( std::string a_strName ) const
|
||||
{
|
||||
for ( auto pLay : m_layers )
|
||||
{
|
||||
if ( pLay->GetName ().compare ( a_strName ) == 0 )
|
||||
{
|
||||
return pLay;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int CTmxReader::GetLayerCount () const
|
||||
uint32_t TmxReader::LidFromGid(uint32_t aGid)
|
||||
{
|
||||
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_gidTable )
|
||||
for (uint32_t first : mGidTable)
|
||||
{
|
||||
if ( uiFirst <= a_uiGid )
|
||||
{
|
||||
return a_uiGid - ( uiFirst - 1 );
|
||||
}
|
||||
if (first <= aGid)
|
||||
return aGid - (first - 1);
|
||||
}
|
||||
|
||||
return a_uiGid;
|
||||
return aGid;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user