[Add] Serialisation stuff.
This commit is contained in:
parent
7d00bfb34a
commit
9ca8983561
@ -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 \
|
||||
|
@ -240,6 +240,10 @@
|
||||
RelativePath="..\..\..\src\libUnuk\LevelGen\MapEntities.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\libUnuk\LevelGen\MapTile.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\libUnuk\LevelGen\MapTile.h"
|
||||
>
|
||||
@ -316,6 +320,18 @@
|
||||
RelativePath="..\..\..\src\libUnuk\System\Rect.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\libUnuk\System\Serialisable.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\libUnuk\System\Serialiser.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\libUnuk\System\Serialiser.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\libUnuk\System\Timer.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;
|
||||
|
||||
// <map> - Let's start parsing the map.
|
||||
rootElem = mapFile.FirstChildElement("map");
|
||||
assert(rootElem != NULL);
|
||||
if(rootElem) {
|
||||
// <line> - 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;
|
||||
|
||||
// <tile> - 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);
|
||||
|
||||
// <tileTexture> - 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());
|
||||
// <tileTexture> - Finished applying the texture, move to the next sibling.
|
||||
|
||||
// <solidTile> - 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);
|
||||
// </solidTile>
|
||||
|
||||
// <entityTexture>
|
||||
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);
|
||||
}
|
||||
// </entityTexture>
|
||||
|
||||
// <SolidEntity>
|
||||
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);
|
||||
// </solidEntity>
|
||||
|
||||
// <zlevel>
|
||||
dataElem = dataElem->NextSiblingElement("zLevel");
|
||||
assert(dataElem != NULL);
|
||||
_tile[x][y].SetZLevel(atoi(dataElem->GetText()));
|
||||
// </zlevel>
|
||||
|
||||
tileElem = tileElem->NextSiblingElement("tile");
|
||||
}
|
||||
//</tile>
|
||||
|
||||
lineElem = lineElem->NextSiblingElement("line");
|
||||
}
|
||||
// </line>
|
||||
}
|
||||
// </map>
|
||||
|
||||
_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];
|
||||
}
|
||||
}
|
@ -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];
|
||||
|
||||
|
@ -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<MapTile>* 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);
|
||||
}
|
@ -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;
|
||||
};
|
||||
|
10
src/libUnuk/System/Serialisable.h
Normal file
10
src/libUnuk/System/Serialisable.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include <stdio.h>
|
||||
|
||||
class Serialiser;
|
||||
|
||||
class Serialisable {
|
||||
public:
|
||||
virtual void Deflate(Serialiser* serialiser) = 0;
|
||||
virtual void Inflate(Serialiser* serialiser) = 0;
|
||||
};
|
171
src/libUnuk/System/Serialiser.cpp
Normal file
171
src/libUnuk/System/Serialiser.cpp
Normal file
@ -0,0 +1,171 @@
|
||||
#include <sstream>
|
||||
|
||||
#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<SerialiserMember>::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<SerialiserMember>::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();
|
||||
}
|
65
src/libUnuk/System/Serialiser.h
Normal file
65
src/libUnuk/System/Serialiser.h
Normal file
@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <tinyxml.h>
|
||||
|
||||
#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<TiXmlElement*> _parentElements;
|
||||
list<SerialiserMember> _members;
|
||||
};
|
Loading…
Reference in New Issue
Block a user