Skip to content

Commit 70bbc0c

Browse files
committed
Support loading a Tileset without a Map.
1 parent cc35261 commit 70bbc0c

8 files changed

Lines changed: 122 additions & 47 deletions

File tree

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<tileset name="platform" class="Level" tilewidth="64" tileheight="64" tilecount="42" columns="6">
3+
<properties>
4+
<property name="bool property" type="bool" value="false"/>
5+
<property name="float property" type="float" value="56.770000000000003"/>
6+
<property name="int property" type="int" value="12"/>
7+
<property name="string property" value="shoes"/>
8+
</properties>
9+
<image source="tileset.png" trans="ff00ff" width="384" height="448"/>
10+
<terraintypes>
11+
<terrain name="brown" tile="-1"/>
12+
<terrain name="green" tile="-1"/>
13+
</terraintypes>
14+
<tile id="0" terrain=",0,,0"/>
15+
<tile id="22" terrain="1,1,1,"/>
16+
<tile id="25" terrain=",1,,1"/>
17+
<tile id="26" terrain="0,,0,"/>
18+
</tileset>
29 KB
Loading
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
tileset by Alucard
2+
http://opengameart.org/content/pixel-art-platformer-complete-pack
6.33 KB
Loading

ParseTest/src/main.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ source distribution.
3030
#include <tmxlite/ObjectGroup.hpp>
3131
#include <tmxlite/LayerGroup.hpp>
3232
#include <tmxlite/TileLayer.hpp>
33+
#include <tmxlite/Tileset.hpp>
3334

3435
#include <iostream>
3536
#include <array>
@@ -70,6 +71,7 @@ void testLoadMap()
7071
{
7172
std::cout << "Tileset: " << tileset.getName() << std::endl;
7273
std::cout << "Tileset class: " << tileset.getClass() << std::endl;
74+
std::cout << "Tileset first GID: " << tileset.getFirstGID() << std::endl;
7375
}
7476

7577
std::cout << "Map has " << mapProperties.size() << " properties" << std::endl;
@@ -172,6 +174,25 @@ void testLoadMap()
172174
}
173175
}
174176

177+
void testLoadTilesetWithoutMap()
178+
{
179+
tmx::Tileset ts;
180+
if (!ts.loadWithoutMap("images/tilemap/platform.tsx"))
181+
{
182+
std::cout << "Failed to load tileset" << std::endl;
183+
return;
184+
}
185+
186+
std::cout << "Loaded tileset without map: " << ts.getName() << std::endl;
187+
std::cout << "Tileset class: " << ts.getClass() << std::endl;
188+
std::cout << "Tileset image: " << ts.getImagePath() << std::endl;
189+
std::cout << "Tileset first GID: " << ts.getFirstGID() << std::endl;
190+
if (ts.getColumnCount() > 0)
191+
{
192+
std::cout << "Tiles in tileset: " << ts.getTileCount() << std::endl;
193+
}
194+
}
195+
175196
class TestFailure {};
176197

177198
template <typename T1, typename T2>
@@ -256,6 +277,8 @@ int main()
256277
{
257278
testLoadMap();
258279
std::cout << std::endl << "------------------------------" << std::endl << std::endl;
280+
testLoadTilesetWithoutMap();
281+
std::cout << std::endl << "------------------------------" << std::endl << std::endl;
259282
testResolvingPaths();
260283
std::cout << std::endl << "------------------------------" << std::endl << std::endl;
261284

tmxlite/include/tmxlite/Tileset.hpp

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ namespace tmx
5252
class TMXLITE_EXPORT_API Tileset final
5353
{
5454
public:
55-
explicit Tileset(const std::string& workingDir);
55+
explicit Tileset(const std::string& workingDir = "");
5656

5757
/*!
5858
\brief Any tiles within a tile set which have special
@@ -130,12 +130,28 @@ namespace tmx
130130
BottomRight
131131
};
132132

133+
/**
134+
\brief Loads the tilemap from the given location.
135+
This does not set the first GID.
136+
This does not support templates.
137+
Usually tilemaps are loaded automatically as part of a Map instead.
138+
*/
139+
bool loadWithoutMap(const std::string& path);
140+
141+
/**
142+
\brief Loads the tilemap from the given XML string.
143+
This does not set the first GID.
144+
This does not support templates.
145+
Usually tilemaps are loaded automatically as part of a Map instead.
146+
*/
147+
bool loadWithoutMapFromString(const std::string& xmlStr);
148+
133149
/*!
134-
\brief Attempts to parse the given xml node.
135-
If node parsing fails an error is printed in the console
150+
\brief Attempts to parse the given xml node as part of a map.
151+
If node parsing fails, an error is printed in the console
136152
and the Tileset remains in an uninitialised state.
137153
*/
138-
void parse(pugi::xml_node, Map*);
154+
bool parse(pugi::xml_node, Map*);
139155

140156
/*!
141157
\brief Returns the first GID of this tile set.
@@ -144,6 +160,12 @@ namespace tmx
144160
*/
145161
std::uint32_t getFirstGID() const { return m_firstGID; }
146162

163+
/*!
164+
\brief Sets the first GID of this tile set.
165+
This is set automatically if the tileset is loaded as part of a Map.
166+
*/
167+
void setFirstGID(std::uint32_t firstGID) { m_firstGID = firstGID; }
168+
147169
/*!
148170
\brief Returns the last GID of this tile set.
149171
This is the ID of the last tile in the tile set.
@@ -284,7 +306,9 @@ namespace tmx
284306
std::vector<std::uint32_t> m_tileIndex;
285307
std::vector<Tile> m_tiles;
286308

287-
void reset();
309+
//always returns false so we can return this
310+
//on load failure
311+
bool reset();
288312

289313
void parseOffsetNode(const pugi::xml_node&);
290314
void parsePropertyNode(const pugi::xml_node&);

tmxlite/src/ObjectGroup.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,6 @@ ObjectGroup::ObjectGroup()
4646
//public
4747
void ObjectGroup::parse(const pugi::xml_node& node, Map* map)
4848
{
49-
assert(map);
50-
5149
std::string attribString = node.name();
5250
if (attribString != "objectgroup")
5351
{

tmxlite/src/Tileset.cpp

Lines changed: 50 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ source distribution.
3838

3939
using namespace tmx;
4040

41+
//public
4142
Tileset::Tileset(const std::string& workingDir)
4243
: m_workingDir (workingDir),
4344
m_firstGID (0),
@@ -52,58 +53,66 @@ Tileset::Tileset(const std::string& workingDir)
5253

5354
}
5455

55-
//public
56-
void Tileset::parse(pugi::xml_node node, Map* map)
56+
bool Tileset::loadWithoutMap(const std::string& path)
5757
{
58-
assert(map);
58+
std::string resolved_path = tmx::resolveFilePath(path, m_workingDir);
59+
std::string contents;
60+
if (!readFileIntoString(resolved_path, &contents))
61+
{
62+
Logger::log("Failed to read file " + resolved_path, Logger::Type::Error);
63+
return reset();
64+
}
5965

60-
std::string attribString = node.name();
61-
if (attribString != "tileset")
66+
m_workingDir = getFilePath(resolved_path);
67+
return loadWithoutMapFromString(contents);
68+
}
69+
70+
bool Tileset::loadWithoutMapFromString(const std::string& xmlStr)
71+
{
72+
pugi::xml_document doc;
73+
auto result = doc.load_string(xmlStr.c_str());
74+
if (!result)
6275
{
63-
Logger::log(attribString + ": not a tileset node! Node will be skipped.", Logger::Type::Warning);
64-
return;
76+
Logger::log("Failed to parse tileset XML", Logger::Type::Error);
77+
Logger::log("Reason: " + std::string(result.description()), Logger::Type::Error);
78+
return false;
6579
}
66-
67-
m_firstGID = node.attribute("firstgid").as_int();
68-
if (m_firstGID == 0)
80+
81+
auto tilesetNode = doc.child("tileset");
82+
if (!tilesetNode)
6983
{
70-
Logger::log("Invalid first GID in tileset. Tileset node skipped.", Logger::Type::Warning);
71-
return;
84+
Logger::log("Failed opening tileset: no tileset node found", Logger::Type::Error);
85+
return reset();
7286
}
7387

74-
pugi::xml_document tsxDoc; //need to keep this in scope
75-
if (node.attribute("source"))
88+
return parse(tilesetNode, nullptr);
89+
}
90+
91+
bool Tileset::parse(pugi::xml_node node, Map* map)
92+
{
93+
std::string attribString = node.name();
94+
95+
//when parsing as part of a map, we may be looking at an inline node that
96+
//refers to another file
97+
if (map)
7698
{
77-
//parse TSX doc
78-
std::string path = node.attribute("source").as_string();
79-
path = resolveFilePath(path, m_workingDir);
80-
81-
//as the TSX file now dictates the image path, the working
82-
//directory is now that of the tsx file
83-
auto position = path.find_last_of('/');
84-
if (position != std::string::npos)
85-
{
86-
m_workingDir = path.substr(0, position);
87-
}
88-
else
99+
if (attribString != "tileset")
89100
{
90-
m_workingDir = "";
101+
Logger::log(attribString + ": not a tileset node! Node will be skipped.", Logger::Type::Warning);
102+
return false;
91103
}
92104

93-
//see if doc can be opened
94-
auto result = tsxDoc.load_file(path.c_str());
95-
if (!result)
105+
m_firstGID = node.attribute("firstgid").as_int();
106+
if (m_firstGID == 0)
96107
{
97-
Logger::log(path + ": Failed opening tsx file for tile set, tile set will be skipped", Logger::Type::Error);
98-
return reset();
108+
Logger::log("Invalid first GID in tileset. Tileset node skipped.", Logger::Type::Warning);
109+
return false;
99110
}
100111

101-
//if it can then replace the current node with tsx node
102-
node = tsxDoc.child("tileset");
103-
if (!node)
112+
if (node.attribute("source"))
104113
{
105-
Logger::log("tsx file does not contain a tile set node, tile set will be skipped", Logger::Type::Error);
106-
return reset();
114+
std::string path = node.attribute("source").as_string();
115+
return loadWithoutMap(path);
107116
}
108117
}
109118

@@ -227,6 +236,8 @@ void Tileset::parse(pugi::xml_node node, Map* map)
227236
createMissingTile(ID);
228237
}
229238
}
239+
240+
return true;
230241
}
231242

232243
std::uint32_t Tileset::getLastGID() const
@@ -249,7 +260,7 @@ const Tileset::Tile* Tileset::getTile(std::uint32_t id) const
249260
}
250261

251262
//private
252-
void Tileset::reset()
263+
bool Tileset::reset()
253264
{
254265
m_firstGID = 0;
255266
m_source = "";
@@ -269,6 +280,7 @@ void Tileset::reset()
269280
m_terrainTypes.clear();
270281
m_tileIndex.clear();
271282
m_tiles.clear();
283+
return false;
272284
}
273285

274286
void Tileset::parseOffsetNode(const pugi::xml_node& node)
@@ -331,8 +343,6 @@ Tileset::Tile& Tileset::newTile(std::uint32_t ID)
331343

332344
void Tileset::parseTileNode(const pugi::xml_node& node, Map* map)
333345
{
334-
assert(map);
335-
336346
Tile& tile = newTile(node.attribute("id").as_int());
337347
if (node.attribute("terrain"))
338348
{

0 commit comments

Comments
 (0)