From 9ca89835610fea29b89dbd6bb4fcdd518b18dfbb Mon Sep 17 00:00:00 2001 From: Tamir Atias Date: Fri, 24 Feb 2012 02:11:06 +0200 Subject: [PATCH] [Add] Serialisation stuff. --- Unuk-QT/Unuk-QT.pro | 4 + Win32/Unuk/LibUnuk/LibUnuk.vcproj | 16 +++ src/libUnuk/LevelGen/LevelGen.cpp | 216 +++++++++--------------------- src/libUnuk/LevelGen/LevelGen.h | 7 +- src/libUnuk/LevelGen/MapTile.cpp | 92 +++++-------- src/libUnuk/LevelGen/MapTile.h | 16 +-- src/libUnuk/System/Serialisable.h | 10 ++ src/libUnuk/System/Serialiser.cpp | 171 +++++++++++++++++++++++ src/libUnuk/System/Serialiser.h | 65 +++++++++ 9 files changed, 373 insertions(+), 224 deletions(-) create mode 100644 src/libUnuk/System/Serialisable.h create mode 100644 src/libUnuk/System/Serialiser.cpp create mode 100644 src/libUnuk/System/Serialiser.h diff --git a/Unuk-QT/Unuk-QT.pro b/Unuk-QT/Unuk-QT.pro index a1cac15..f916292 100644 --- a/Unuk-QT/Unuk-QT.pro +++ b/Unuk-QT/Unuk-QT.pro @@ -19,6 +19,8 @@ HEADERS += ../src/Libs/wglext.h \ ../src/libUnuk/Sprite/Texture.h \ ../src/libUnuk/Sprite/ImageLoader.h \ ../src/libUnuk/Sprite/ApplySurface.h \ + ../src/libUnuk/System/Serialisation.h \ + ../src/libUnuk/System/Serialisable.h \ ../src/libUnuk/System/Rect.h \ ../src/libUnuk/System/Input.h \ ../src/libUnuk/System/FPS.h \ @@ -57,6 +59,7 @@ SOURCES += ../src/libUnuk/Engine/WorldManager.cpp \ ../src/libUnuk/Sprite/Texture.cpp \ ../src/libUnuk/Sprite/ImageLoader.cpp \ ../src/libUnuk/Sprite/ApplySurface.cpp \ + ../src/libUnuk/System/Serialisation.cpp \ ../src/libUnuk/System/Timer.cpp \ ../src/libUnuk/System/Rect.cpp \ ../src/libUnuk/System/Input.cpp \ @@ -76,6 +79,7 @@ SOURCES += ../src/libUnuk/Engine/WorldManager.cpp \ ../src/libUnuk/LevelGen/LevelGen.cpp \ ../src/libUnuk/LevelGen/MapEntities.cpp \ ../src/libUnuk/LevelGen/MapElement.cpp \ + ../src/libUnuk/LevelGen/MapTile.cpp \ ../src/libUnuk/LevelGen/AStarTile.cpp \ ../src/libUnuk/UI/EventHistory.cpp \ ../src/libUnuk/UI/Bar.cpp \ diff --git a/Win32/Unuk/LibUnuk/LibUnuk.vcproj b/Win32/Unuk/LibUnuk/LibUnuk.vcproj index d61567c..b253a8b 100644 --- a/Win32/Unuk/LibUnuk/LibUnuk.vcproj +++ b/Win32/Unuk/LibUnuk/LibUnuk.vcproj @@ -240,6 +240,10 @@ RelativePath="..\..\..\src\libUnuk\LevelGen\MapEntities.h" > + + @@ -316,6 +320,18 @@ RelativePath="..\..\..\src\libUnuk\System\Rect.h" > + + + + + + diff --git a/src/libUnuk/LevelGen/LevelGen.cpp b/src/libUnuk/LevelGen/LevelGen.cpp index a349d55..962bf96 100644 --- a/src/libUnuk/LevelGen/LevelGen.cpp +++ b/src/libUnuk/LevelGen/LevelGen.cpp @@ -2,6 +2,7 @@ #include "LevelGen.h" #include "../Engine/NPC.h" +#include "../System/Serialiser.h" #include "../../Unuk/Player.h" LevelGen::LevelGen(void) : _world(this) { @@ -28,7 +29,6 @@ void LevelGen::New(void) { _tile[x][y].SetTileSolidity(false); _tile[x][y].SetTileXY(x * TILE_WIDTH, y * TILE_HEIGHT); _tile[x][y].SetEntitySolidity(false); - _tile[x][y].SetZLevel(100); } } @@ -41,103 +41,14 @@ void LevelGen::New(void) { void LevelGen::Load(const string& filename) { Unload(); + _currentMap = filename; string fullMapPath = "../Data/Media/Maps/" + filename; - TiXmlDocument mapFile(fullMapPath.c_str()); - assert(mapFile.LoadFile() == true); + Serialiser serialiser; + serialiser.Load(fullMapPath); + Inflate(&serialiser); - // Getting dirty with some XML. This seems like a nicer - // approach to loading maps, rather than parsing text files. - TiXmlElement* rootElem = NULL; - TiXmlElement* lineElem = NULL; - TiXmlElement* tileElem = NULL; - TiXmlElement* dataElem = NULL; - - x = -1; - y = -1; - - // - Let's start parsing the map. - rootElem = mapFile.FirstChildElement("map"); - assert(rootElem != NULL); - if(rootElem) { - // - We want to tile one line at a time. line represents - // the row we are tiling. - lineElem = rootElem->FirstChildElement("line"); - assert(lineElem != NULL); - while(lineElem) { - y++; - x = -1; - - // - Then we will select the tile. and increment x to keep tiling that row. - tileElem = lineElem->FirstChildElement("tile"); - assert(tileElem != NULL); - while(tileElem) { - x++; - _tile[x][y].SetTileXY(x * TILE_WIDTH, y * TILE_HEIGHT); - - // - Apply a teture to the tile. - dataElem = tileElem->FirstChildElement("tileTexture"); - assert(dataElem != NULL); - stringstream tilePath; - tilePath << "../Data/Media/Images/Tiles/" << dataElem->GetText() << ".png"; - _tile[x][y].SetTileTexture(_tileTextures.Add(tilePath.str())); - _tile[x][y].SetTileTextureName(dataElem->GetText()); - // - Finished applying the texture, move to the next sibling. - - // - Check to see if the tile is solid or not. - dataElem = dataElem->NextSiblingElement("solidTile"); - assert(dataElem != NULL); - string tileSolidity = dataElem->GetText(); - assert(tileSolidity == "false" || tileSolidity == "true"); - if(tileSolidity == "false") - _tile[x][y].SetTileSolidity(false); - else - _tile[x][y].SetTileSolidity(true); - // - - // - dataElem = dataElem->NextSiblingElement("entityTexture"); - assert(dataElem != NULL); - string entityName = dataElem->GetText(); - if(entityName != "null") { - stringstream entityPath; - entityPath << "../Data/Media/Images/Entities/" << entityName << ".png"; - _tile[x][y].SetEntityTexture(_entityTextures.AddAlpha(entityPath.str())); - _tile[x][y].SetEntityTextureName(entityName); - - _tile[x][y].SetEntityXY(_tile[x][y].GetTileX() + TILE_WIDTH / 2 - _tile[x][y].GetEntityWidth() / 2, - _tile[x][y].GetTileY() + TILE_HEIGHT / 2 - _tile[x][y].GetEntityHeight() / 2); - } - // - - // - dataElem = dataElem->NextSiblingElement("solidEntity"); - assert(dataElem != NULL); - string entitySolidity = dataElem->GetText(); - assert(entitySolidity == "false" || entitySolidity == "true"); - if(entitySolidity == "false") - _tile[x][y].SetEntitySolidity(false); - else - _tile[x][y].SetEntitySolidity(true); - // - - // - dataElem = dataElem->NextSiblingElement("zLevel"); - assert(dataElem != NULL); - _tile[x][y].SetZLevel(atoi(dataElem->GetText())); - // - - tileElem = tileElem->NextSiblingElement("tile"); - } - // - - lineElem = lineElem->NextSiblingElement("line"); - } - // - } - // - _world = WorldManager(this); GenerateEnemies(); @@ -145,59 +56,15 @@ void LevelGen::Load(const string& filename) { UpdateAStarTiles(); } -void LevelGen::Save(const string& filename){ - TiXmlDocument doc; - - TiXmlElement* rootElem = new TiXmlElement("map"); - - for(y = 0; y < TILE_ARRAY_HEIGHT; y++) { - TiXmlElement* lineElem = new TiXmlElement("line"); - - for(x = 0; x < TILE_ARRAY_WIDTH; x++) { - TiXmlElement* tileElem = new TiXmlElement("tile"); - - TiXmlElement* tileTextureElem = new TiXmlElement("tileTexture"); - TiXmlText* tileTextureText = new TiXmlText(_tile[x][y].GetTileTextureName().c_str()); - tileTextureElem->LinkEndChild(tileTextureText); - - TiXmlElement* solidTileElem = new TiXmlElement("solidTile"); - TiXmlText* solidTileText = new TiXmlText(_tile[x][y].GetTileSolidity() ? "true" : "false"); - solidTileElem->LinkEndChild(solidTileText); - - string entityTextureName = _tile[x][y].GetEntityTextureName(); - - TiXmlElement* entityTextureElem = new TiXmlElement("entityTexture"); - TiXmlText* entityTextureText = new TiXmlText(entityTextureName.empty() ? "null" : entityTextureName.c_str()); - entityTextureElem->LinkEndChild(entityTextureText); - - TiXmlElement* solidEntityElem = new TiXmlElement("solidEntity"); - TiXmlText* solidEntityText = new TiXmlText(_tile[x][y].GetEntitySolitity() ? "true" : "false"); - solidEntityElem->LinkEndChild(solidEntityText); - - stringstream zLevelStr; - zLevelStr << _tile[x][y].GetZLevel(); - - TiXmlElement* zLevelElem = new TiXmlElement("zLevel"); - TiXmlText* zLevelText = new TiXmlText(zLevelStr.str().c_str()); - zLevelElem->LinkEndChild(zLevelText); - - tileElem->LinkEndChild(tileTextureElem); - tileElem->LinkEndChild(solidTileElem); - tileElem->LinkEndChild(entityTextureElem); - tileElem->LinkEndChild(solidEntityElem); - tileElem->LinkEndChild(zLevelElem); - - lineElem->LinkEndChild(tileElem); - } - - rootElem->LinkEndChild(lineElem); - } - +void LevelGen::Save(const string& filename) { + Serialiser serialiser; + Deflate(&serialiser); + _currentMap = filename; string fullMapPath = "../Data/Media/Maps/" + filename; - doc.LinkEndChild(rootElem); - doc.SaveFile(fullMapPath.c_str()); + serialiser.Save(fullMapPath); + } void LevelGen::Update(void) { @@ -318,11 +185,6 @@ void LevelGen::FindSpawnPoint(int& xArg, int& yArg, int objWidth, int objHeight) for(int i = 0; i < TILE_ARRAY_WIDTH; i++) { for(int j = 0; j < TILE_ARRAY_HEIGHT; j++) { - if(_tile[i][j].GetTileSolidity()) { - FindSpawnPoint(xArg, yArg, objWidth, objHeight); - return; - } - if(_tile[i][j].GetEntitySolitity()) { SDL_Rect entityRect; entityRect.x = _tile[i][j].GetEntityX(); @@ -460,6 +322,56 @@ void LevelGen::UpdateAStarTiles(void) { } } +void LevelGen::Deflate(Serialiser* serialiser) { + serialiser->StepIn("map"); + for(int y = 0; y < TILE_ARRAY_HEIGHT; y++) { + serialiser->StepIn("line"); + for(int x = 0; x < TILE_ARRAY_WIDTH; x++) { + serialiser->StepIn("tile"); + _tile[x][y].Deflate(serialiser); + serialiser->StepOut(); + } + serialiser->StepOut(); + } + serialiser->StepOut(); +} + +void LevelGen::Inflate(Serialiser* serialiser) { + serialiser->FirstElement("map"); + + x = 0; + y = 0; + + while(serialiser->NextElement("line")) { + x = 0; + while(serialiser->NextElement("tile")) { + _tile[x][y].Inflate(serialiser); + x++; + } + serialiser->RollBack(); + y++; + } + + for(x = 0; x < TILE_ARRAY_WIDTH; x++) { + for(y = 0; y < TILE_ARRAY_HEIGHT; y++) { + string tileTextureName = _tile[x][y].GetTileTextureName(); + if(tileTextureName != "null") { + _tile[x][y].SetTileTexture(_tileTextures.AddAlpha("../Data/Media/Images/Tiles/" + tileTextureName + ".png")); + _tile[x][y].SetTileXY(x * TILE_WIDTH, y * TILE_HEIGHT); + } + + string entityTextureName = _tile[x][y].GetEntityTextureName(); + if(entityTextureName != "null") { + _tile[x][y].SetEntityTexture(_entityTextures.AddAlpha("../Data/Media/Images/Entities/" + entityTextureName + ".png")); + _tile[x][y].SetEntityXY(_tile[x][y].GetTileX() + TILE_WIDTH / 2 - _tile[x][y].GetEntityWidth() / 2, + _tile[x][y].GetTileY() + TILE_HEIGHT / 2 - _tile[x][y].GetEntityHeight() / 2); + } + + + } + } +} + string LevelGen::GetCurrentMap(void) { return _currentMap; } @@ -500,10 +412,6 @@ int LevelGen::GetEntityHeight(int xArg, int yArg) { return _tile[xArg + 1][yArg + 1].GetEntityHeight(); } -int LevelGen::GetTileZLevel(int xArg, int yArg) { - return _tile[xArg + 1][yArg + 1].GetZLevel(); -} - AStarTile& LevelGen::GetAStarTile(int xArg, int yArg) { return _astarTile[xArg][yArg]; -} +} \ No newline at end of file diff --git a/src/libUnuk/LevelGen/LevelGen.h b/src/libUnuk/LevelGen/LevelGen.h index 2cf4135..3a96eac 100644 --- a/src/libUnuk/LevelGen/LevelGen.h +++ b/src/libUnuk/LevelGen/LevelGen.h @@ -14,6 +14,7 @@ #include "../LevelGen/MapTile.h" #include "../LevelGen/AStarTile.h" #include "../System/Debug.h" +#include "../System/Serialisable.h" #include "../Engine/WorldManager.h" #include "../Engine/MemClass.h" using namespace std; @@ -21,7 +22,7 @@ using namespace std; class Character; class Player; -class LevelGen { +class LevelGen : public Serialisable { public: LevelGen(void); ~LevelGen(void); @@ -70,11 +71,13 @@ private: bool AStarTilePassable(int xArg, int yArg); void UpdateAStarTiles(void); + void Deflate(Serialiser* serialiser); + void Inflate(Serialiser* serialiser); + string _currentMap; int x; int y; - MapTile _tile[TILE_ARRAY_WIDTH][TILE_ARRAY_HEIGHT]; AStarTile _astarTile[ASTAR_ARRAY_WIDTH][ASTAR_ARRAY_HEIGHT]; diff --git a/src/libUnuk/LevelGen/MapTile.cpp b/src/libUnuk/LevelGen/MapTile.cpp index 3a461d4..c8c3a80 100644 --- a/src/libUnuk/LevelGen/MapTile.cpp +++ b/src/libUnuk/LevelGen/MapTile.cpp @@ -1,66 +1,42 @@ #include "MapTile.h" -#include "LevelGen.h" -MapTile::MapTile(const MapTile& source) { - _level = source._level; - _tile = source._tile; - _entity = source._entity; - _zLevel = source._zLevel; +void MapTile::Deflate(Serialiser* serialiser) { + string tileTexture = _tile.GetTextureName(); + bool solidTile = _tile.GetSolidity(); + string entityTexture = _entity.GetTextureName(); + bool solidEntity = _entity.GetSolidity(); + + if(tileTexture.empty()) { + tileTexture = "null"; + } + if(entityTexture.empty()) { + entityTexture = "null"; + } + + serialiser->RegisterMember("tileTexture", MEMBER_STRING, &tileTexture); + serialiser->RegisterMember("solidTile", MEMBER_BOOL, &solidTile); + serialiser->RegisterMember("entityTexture", MEMBER_STRING, &entityTexture); + serialiser->RegisterMember("solidEntity", MEMBER_BOOL, &solidEntity); + + serialiser->WriteMembers(); } -bool MapTile::IsSameState(MapTile& tile) { - return (tile.GetTileX() == _tile.GetX()) && (tile.GetTileY() == _tile.GetY()); -} +void MapTile::Inflate(Serialiser* serialiser) { + string tileTexture; + bool solidTile; + string entityTexture; + bool solidEntity; -bool MapTile::IsGoal(MapTile& tile) { - return IsSameState(tile); -} + serialiser->RegisterMember("tileTexture", MEMBER_STRING, &tileTexture); + serialiser->RegisterMember("solidTile", MEMBER_BOOL, &solidTile); + serialiser->RegisterMember("entityTexture", MEMBER_STRING, &entityTexture); + serialiser->RegisterMember("solidEntity", MEMBER_BOOL, &solidEntity); -float MapTile::GoalDistanceEstimate(MapTile& goal) { - Vec2 thisPos(_tile.GetX(), _tile.GetY()); - Vec2 goalPos(goal.GetTileX(), goal.GetTileY()); - return fabs(Vec2::DistanceSquared(thisPos, goalPos)); -} + serialiser->ReadMembers(); -float MapTile::GetCost(MapTile& goal) { - return 64.0f*64.0f; -} + _tile.SetTextureName(tileTexture); + _tile.SetSolidity(solidTile); -bool MapTile::GetSuccessors(AStarSearch* search, MapTile* parent) { - int tileX = _tile.GetX() / TILE_WIDTH; - int tileY = _tile.GetY() / TILE_HEIGHT; - - // Add tile to the left if possible. - if(tileX > 0) { - MapTile& successor = _level->GetTile(tileX - 1, tileY); - if(successor.GetTileSolidity() || successor.GetEntitySolitity()) { - search->AddSuccessor(successor); - } - } - - // Add tile to the right if possible - if(tileX < TILE_WIDTH) { - MapTile& successor = _level->GetTile(tileX + 1, tileY); - if(successor.GetTileSolidity() || successor.GetEntitySolitity()) { - search->AddSuccessor(successor); - } - } - - // Add tile to the bottom if possible - if(tileY > 0) { - MapTile& successor = _level->GetTile(tileX, tileY - 1); - if(successor.GetTileSolidity() || successor.GetEntitySolitity()) { - search->AddSuccessor(successor); - } - } - - // Add tile to the top if possible - if(tileY < TILE_HEIGHT) { - MapTile& successor = _level->GetTile(tileX, tileY + 1); - if(successor.GetTileSolidity() || successor.GetEntitySolitity()) { - search->AddSuccessor(successor); - } - } - - return true; -} + _entity.SetTextureName(entityTexture); + _entity.SetSolidity(solidEntity); +} \ No newline at end of file diff --git a/src/libUnuk/LevelGen/MapTile.h b/src/libUnuk/LevelGen/MapTile.h index 3196e34..4265748 100644 --- a/src/libUnuk/LevelGen/MapTile.h +++ b/src/libUnuk/LevelGen/MapTile.h @@ -7,15 +7,20 @@ #include "../Sprite/ApplySurface.h" #include "../LevelGen/MapElement.h" #include "../LevelGen/MapEntities.h" +#include "../System/Serialisable.h" +#include "../System/Serialiser.h" using namespace std; -class MapTile { +class MapTile : public Serialisable { public: MapTile(void) { } ~MapTile(void) { } void Render(void) { _tile.Render(), _entity.Render(); } + void Deflate(Serialiser* serialiser); + void Inflate(Serialiser* serialiser); + // Tile Mutators. SDL_Surface* SetTileTexture(SDL_Surface* arg) { _tile.SetTexture(arg); return NULL; } void SetTileTextureName(string path) { _tile.SetTextureName(path); } @@ -29,7 +34,6 @@ public: int GetTileX(void) { return _tile.GetX(); } int GetTileY(void) { return _tile.GetY(); } - // Entity Mutators. void SetEntityTexture(SDL_Surface* arg) { _entity.SetTexture(arg); } void SetEntityTextureName(string path) { _entity.SetTextureName(path); } @@ -44,15 +48,7 @@ public: int GetEntityHeight(void) { return _entity.GetHeight(); } string GetEntityTextureName(void) { return _entity.GetTextureName(); } - // ZLevel Mutators. - void SetZLevel(int arg) { _zLevel = arg; } - int GetZLevel(void) { return _zLevel; } - private: MapElement _tile; MapEntityGeneric _entity; - - // -1 is a 'special' tile, the next tile that the player walks - // on is the players new zlevel. - int _zLevel; }; diff --git a/src/libUnuk/System/Serialisable.h b/src/libUnuk/System/Serialisable.h new file mode 100644 index 0000000..381eb90 --- /dev/null +++ b/src/libUnuk/System/Serialisable.h @@ -0,0 +1,10 @@ +#pragma once +#include + +class Serialiser; + +class Serialisable { +public: + virtual void Deflate(Serialiser* serialiser) = 0; + virtual void Inflate(Serialiser* serialiser) = 0; +}; diff --git a/src/libUnuk/System/Serialiser.cpp b/src/libUnuk/System/Serialiser.cpp new file mode 100644 index 0000000..54c5a26 --- /dev/null +++ b/src/libUnuk/System/Serialiser.cpp @@ -0,0 +1,171 @@ +#include + +#include "Serialiser.h" +#include "Debug.h" + +void Serialiser::StepIn(const string& name) { + if(_currentElement != NULL) { + // Save the current element as a parent element. + _parentElements.push_back(_currentElement); + } + + // Create the new element. + _currentElement = new TiXmlElement(name.c_str()); + + if(_rootElement == NULL) { + _rootElement = _currentElement; + _parentElements.push_back(_rootElement); + } +} + +void Serialiser::StepOut(void) { + if(_parentElements.size() == 0) { + return; + } + + TiXmlElement* parentElement = _parentElements.back(); + + // This happens when stepping out of root. + if(parentElement == _currentElement) { + return; + } + + // Append the current element to the end of the parent element. + parentElement->LinkEndChild(_currentElement); + + // Set the current element to be the parent element. + _currentElement = parentElement; + + // Remove the current element from the parent elements list. + _parentElements.pop_back(); +} + +bool Serialiser::FirstElement(const string& name) { + TiXmlElement* oldElement = _currentElement; + + if(!_currentElement) { + _currentElement = _document.FirstChildElement(name.c_str()); + } else { + _currentElement = _currentElement->FirstChildElement(name.c_str()); + } + + if(!_currentElement) { + // Restore the old element if new one was not found. + _currentElement = oldElement; + + return false; + } + + if(oldElement) { + // Save the old element as parent. + _parentElements.push_back(oldElement); + } + + return true; +} + +bool Serialiser::NextElement(const string& name) { + // Find first element of that name if current one is + // not named the same. + if(name != _currentElement->Value()) { + return FirstElement(name); + } + + TiXmlElement* oldElement = _currentElement; + + _currentElement = _currentElement->NextSiblingElement(name.c_str()); + + if(!_currentElement) { + // Restore the old element if new one was not found. + _currentElement = oldElement; + + return false; + } + + return true; +} + +void Serialiser::RollBack(void) { + if(_parentElements.size() > 0) { + _currentElement = _parentElements.back(); + _parentElements.pop_back(); + } +} + +void Serialiser::Load(const string& filename) { + _document.LoadFile(filename.c_str()); +} + +void Serialiser::Save(const string& filename) { + _document.LinkEndChild(_rootElement); + _document.SaveFile(filename.c_str()); +} + +void Serialiser::RegisterMember(const string& name, int type, void* data) { + SerialiserMember member(name, type, data); + _members.push_back(member); +} + +void Serialiser::WriteMembers(void) { + Debug::logger->message("WriteMembers()"); + + std::stringstream sstream; + + for(list::iterator i = _members.begin(); i != _members.end(); ++i) { + TiXmlText* text = NULL; + + // Convert the data to text. + if(i->_type == MEMBER_INT) { + sstream.clear(); + sstream << *((int*)i->_data); + text = new TiXmlText(sstream.str().c_str()); + } else if(i->_type == MEMBER_FLOAT) { + sstream.clear(); + sstream << *((float*)i->_data); + text = new TiXmlText(sstream.str().c_str()); + } else if(i->_type == MEMBER_STRING) { + text = new TiXmlText((*((string*)i->_data)).c_str()); + } else if(i->_type == MEMBER_BOOL) { + bool b = *((bool*)i->_data); + text = new TiXmlText(b ? "true" : "false"); + } + + if(!text) { + continue; + } + + TiXmlElement* element = new TiXmlElement(i->_name.c_str()); + element->LinkEndChild(text); + + _currentElement->LinkEndChild(element); + } + + _members.clear(); +} + +void Serialiser::ReadMembers(void) { + for(list::iterator i = _members.begin(); i != _members.end(); ++i) { + TiXmlElement* element = _currentElement->FirstChildElement(i->_name.c_str()); + + if(!element) { + continue; + } + + // Read the data from the text of the element. + if(i->_type == MEMBER_INT) { + *((int*)i->_data) = atoi(element->GetText()); + } else if(i->_type == MEMBER_FLOAT) { + *((float*)i->_data) = (float)atof(element->GetText()); + } else if(i->_type == MEMBER_STRING) { + *((string*)i->_data) = string(element->GetText()); + } else if(i->_type == MEMBER_BOOL) { + if(!strcmp(element->GetText(), "true")) { + *((bool*)i->_data) = true; + } else { + *((bool*)i->_data) = false; + } + } + } + + _members.clear(); +} diff --git a/src/libUnuk/System/Serialiser.h b/src/libUnuk/System/Serialiser.h new file mode 100644 index 0000000..9a095d3 --- /dev/null +++ b/src/libUnuk/System/Serialiser.h @@ -0,0 +1,65 @@ +#pragma once +#include +#include +#include + +#include "Serialisable.h" + +using std::string; +using std::list; + +enum { + MEMBER_INT, + MEMBER_FLOAT, + MEMBER_BOOL, + MEMBER_STRING, +}; + +class SerialiserMember { +public: + SerialiserMember(const string& name, int type, void* data) : _name(name), _type(type), _data(data) {} + + string _name; + int _type; + void* _data; +}; + +class Serialiser { +public: + Serialiser(void) : _rootElement(NULL), _currentElement(NULL) {} + + // SERIALISATION: + // StepIn should be called when a new list of elements/members needs to be created (go further down the tree). + // StepOut should be called every time the processing of an element is complete (go further up the tree). + void StepIn(const string& name); + void StepOut(void); + + // DESERIALISATION: + // FirstElement is used to find the first child element of the current element. + // NextElement should be called whenever the next element is requested, if another element + // was found, it will return true. + // RollBack will just go back to the parent element. + bool FirstElement(const string& name); + bool NextElement(const string& name); + void RollBack(void); + + // Load should be called before the deserialisation. + // Save should be called after the serialisation. + void Load(const string& filename); + void Save(const string& filename); + + // The members of the element should all be registered with RegisterMember. + // If serialisation is done, WriteMembers should be called after registration, otherwise, + // ReadMembers should be called after registration. After ReadMembers/WriteMembers is called, + // the list of members is clear. + void RegisterMember(const string& name, int _type, void* data); + void WriteMembers(void); + void ReadMembers(void); + +private: + TiXmlDocument _document; + TiXmlElement* _rootElement; + TiXmlElement* _currentElement; + list _parentElements; + list _members; +};