1
0
mirror of https://github.com/ScrelliCopter/tmx2gba.git synced 2025-02-21 03:29:25 +11:00
This commit is contained in:
2022-09-07 02:34:09 +10:00
parent 6c2cca3fd5
commit a5ac1d9bfe
12 changed files with 470 additions and 735 deletions

View File

@@ -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;
}