Skip to content

Commit ab9a342

Browse files
authored
Merge pull request #2025 from Narre/nested_tilesets
Tiles from other tilesets can now be imported from the strf files
2 parents 0a05083 + ee8359b commit ab9a342

File tree

2 files changed

+107
-61
lines changed

2 files changed

+107
-61
lines changed

src/supertux/tile_set_parser.cpp

Lines changed: 104 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,24 @@ TileSetParser::TileSetParser(TileSet& tileset, const std::string& filename) :
3939
}
4040

4141
void
42-
TileSetParser::parse()
42+
TileSetParser::parse(int32_t start, int32_t end, int32_t offset, bool imported)
4343
{
44+
if (offset && start + offset < 1) {
45+
start = -offset + 1;
46+
log_warning << "The defined offset would assign non-positive ids to tiles, tiles below " << -offset + 1 << " will be ignored." << std::endl;
47+
}
48+
if (end < 0) {
49+
log_warning << "Cannot import tiles with negative IDs." << std::endl;
50+
return;
51+
}
52+
if (start < 0) {
53+
log_warning << "Cannot import tiles with negative IDs. Importing will start at ID 1." << std::endl;
54+
start = 1;
55+
}
56+
if (imported && !end) {
57+
log_warning << "Importing a tileset with no upper ID limit can cause ID conflicts if the imported tileset is expanded in the future." <<std::endl;
58+
}
59+
4460
m_tiles_path = FileSystem::dirname(m_filename);
4561

4662
auto doc = ReaderDocument::from_file(m_filename);
@@ -56,11 +72,13 @@ TileSetParser::parse()
5672
if (iter.get_key() == "tile")
5773
{
5874
ReaderMapping tile_mapping = iter.as_mapping();
59-
parse_tile(tile_mapping);
75+
parse_tile(tile_mapping, start, end, offset);
6076
}
6177
else if (iter.get_key() == "tilegroup")
6278
{
6379
/* tilegroups are only interesting for the editor */
80+
/* ignore tilegroups for imported tilesets */
81+
if (imported) continue;
6482
ReaderMapping reader = iter.as_mapping();
6583
Tilegroup tilegroup;
6684
reader.get("name", tilegroup.name);
@@ -70,10 +88,12 @@ TileSetParser::parse()
7088
else if (iter.get_key() == "tiles")
7189
{
7290
ReaderMapping tiles_mapping = iter.as_mapping();
73-
parse_tiles(tiles_mapping);
91+
parse_tiles(tiles_mapping, start, end, offset);
7492
}
7593
else if (iter.get_key() == "autotileset")
7694
{
95+
/* ignore autotiles for imported tilesets */
96+
if (imported) continue;
7797
ReaderMapping reader = iter.as_mapping();
7898
std::string autotile_filename;
7999
if (!reader.get("source", autotile_filename))
@@ -87,25 +107,51 @@ TileSetParser::parse()
87107
parser->parse();
88108
}
89109
}
110+
else if (iter.get_key() == "import-tileset")
111+
{
112+
ReaderMapping reader = iter.as_mapping();
113+
std::string import_filename;
114+
int32_t import_start = 0, import_end = 0, import_offset = 0;
115+
reader.get("file", import_filename);
116+
reader.get("start", import_start);
117+
reader.get("end", import_end);
118+
reader.get("offset", import_offset);
119+
if (import_start + import_offset < start) {
120+
import_start = (start - import_offset) < 0 ? 0 : (start - import_offset);
121+
}
122+
if (end && (!import_end || (import_end + import_offset) > end)) {
123+
import_end = end - import_offset;
124+
}
125+
if (import_end < import_start) {
126+
if (!imported) log_warning << "The defined range has a negative size, no tiles will be imported." << std::endl;
127+
continue;
128+
}
129+
import_offset += offset;
130+
TileSetParser import_parser(m_tileset, import_filename);
131+
import_parser.parse(import_start, import_end, import_offset, true);
132+
}
90133
else
91134
{
92135
log_warning << "Unknown symbol '" << iter.get_key() << "' in tileset file" << std::endl;
93136
}
94137
}
95-
if (g_config->developer_mode)
138+
/* only create the unassigned tilegroup from the parent strf */
139+
if (g_config->developer_mode && !imported)
96140
{
97141
m_tileset.add_unassigned_tilegroup();
98142
}
99143
}
100144

101145
void
102-
TileSetParser::parse_tile(const ReaderMapping& reader)
146+
TileSetParser::parse_tile(const ReaderMapping& reader, int32_t min, int32_t max, int32_t offset)
103147
{
104148
uint32_t id;
105149
if (!reader.get("id", id))
106150
{
107151
throw std::runtime_error("Missing tile-id.");
108152
}
153+
if (max && (id < static_cast<uint32_t>(min) || id > static_cast<uint32_t>(max))) return;
154+
id += offset;
109155

110156
uint32_t attributes = 0;
111157

@@ -182,7 +228,7 @@ TileSetParser::parse_tile(const ReaderMapping& reader)
182228
}
183229

184230
void
185-
TileSetParser::parse_tiles(const ReaderMapping& reader)
231+
TileSetParser::parse_tiles(const ReaderMapping& reader, int32_t min, int32_t max, int32_t offset)
186232
{
187233
// List of ids (use 0 if the tile should be ignored)
188234
std::vector<uint32_t> ids;
@@ -271,65 +317,65 @@ TileSetParser::parse_tiles(const ReaderMapping& reader)
271317

272318
for (size_t i = 0; i < ids.size(); ++i)
273319
{
274-
if (ids[i] != 0)
275-
{
276-
const int x = static_cast<int>(32 * (i % width));
277-
const int y = static_cast<int>(32 * (i / width));
278-
279-
std::vector<SurfacePtr> regions;
280-
regions.reserve(surfaces.size());
281-
std::transform(surfaces.begin(), surfaces.end(), std::back_inserter(regions),
282-
[x, y] (const SurfacePtr& surface) {
283-
return surface->region(Rect(x, y, Size(32, 32)));
284-
});
285-
286-
std::vector<SurfacePtr> editor_regions;
287-
editor_regions.reserve(editor_surfaces.size());
288-
std::transform(editor_surfaces.begin(), editor_surfaces.end(), std::back_inserter(editor_regions),
289-
[x, y] (const SurfacePtr& surface) {
290-
return surface->region(Rect(x, y, Size(32, 32)));
291-
});
292-
293-
auto tile = std::make_unique<Tile>(regions,
294-
editor_regions,
295-
(has_attributes ? attributes[i] : 0),
296-
(has_datas ? datas[i] : 0),
297-
fps);
298-
299-
m_tileset.add_tile(ids[i], std::move(tile));
300-
}
320+
if (!ids[i] || (max && (ids[i] < static_cast<uint32_t>(min) || ids[i] > static_cast<uint32_t>(max)))) continue;
321+
ids[i] += offset;
322+
323+
const int x = static_cast<int>(32 * (i % width));
324+
const int y = static_cast<int>(32 * (i / width));
325+
326+
std::vector<SurfacePtr> regions;
327+
regions.reserve(surfaces.size());
328+
std::transform(surfaces.begin(), surfaces.end(), std::back_inserter(regions),
329+
[x, y] (const SurfacePtr& surface) {
330+
return surface->region(Rect(x, y, Size(32, 32)));
331+
});
332+
333+
std::vector<SurfacePtr> editor_regions;
334+
editor_regions.reserve(editor_surfaces.size());
335+
std::transform(editor_surfaces.begin(), editor_surfaces.end(), std::back_inserter(editor_regions),
336+
[x, y] (const SurfacePtr& surface) {
337+
return surface->region(Rect(x, y, Size(32, 32)));
338+
});
339+
340+
auto tile = std::make_unique<Tile>(regions,
341+
editor_regions,
342+
(has_attributes ? attributes[i] : 0),
343+
(has_datas ? datas[i] : 0),
344+
fps);
345+
346+
m_tileset.add_tile(ids[i], std::move(tile));
301347
}
302348
}
303349
else // (!shared_surface)
304350
{
305351
for (size_t i = 0; i < ids.size(); ++i)
306352
{
307-
if (ids[i] != 0)
308-
{
309-
int x = static_cast<int>(32 * (i % width));
310-
int y = static_cast<int>(32 * (i / width));
311-
312-
std::vector<SurfacePtr> surfaces;
313-
boost::optional<ReaderMapping> surfaces_mapping;
314-
if (reader.get("image", surfaces_mapping) ||
315-
reader.get("images", surfaces_mapping)) {
316-
surfaces = parse_imagespecs(*surfaces_mapping, Rect(x, y, Size(32, 32)));
317-
}
318-
319-
std::vector<SurfacePtr> editor_surfaces;
320-
boost::optional<ReaderMapping> editor_surfaces_mapping;
321-
if (reader.get("editor-images", editor_surfaces_mapping)) {
322-
editor_surfaces = parse_imagespecs(*editor_surfaces_mapping, Rect(x, y, Size(32, 32)));
323-
}
324-
325-
auto tile = std::make_unique<Tile>(surfaces,
326-
editor_surfaces,
327-
(has_attributes ? attributes[i] : 0),
328-
(has_datas ? datas[i] : 0),
329-
fps);
330-
331-
m_tileset.add_tile(ids[i], std::move(tile));
353+
if(!ids[i] || (max && (ids[i] < static_cast<uint32_t>(min) || ids[i] > static_cast<uint32_t>(max)))) continue;
354+
ids[i] += offset;
355+
356+
int x = static_cast<int>(32 * (i % width));
357+
int y = static_cast<int>(32 * (i / width));
358+
359+
std::vector<SurfacePtr> surfaces;
360+
boost::optional<ReaderMapping> surfaces_mapping;
361+
if (reader.get("image", surfaces_mapping) ||
362+
reader.get("images", surfaces_mapping)) {
363+
surfaces = parse_imagespecs(*surfaces_mapping, Rect(x, y, Size(32, 32)));
364+
}
365+
366+
std::vector<SurfacePtr> editor_surfaces;
367+
boost::optional<ReaderMapping> editor_surfaces_mapping;
368+
if (reader.get("editor-images", editor_surfaces_mapping)) {
369+
editor_surfaces = parse_imagespecs(*editor_surfaces_mapping, Rect(x, y, Size(32, 32)));
332370
}
371+
372+
auto tile = std::make_unique<Tile>(surfaces,
373+
editor_surfaces,
374+
(has_attributes ? attributes[i] : 0),
375+
(has_datas ? datas[i] : 0),
376+
fps);
377+
378+
m_tileset.add_tile(ids[i], std::move(tile));
333379
}
334380
}
335381
}

src/supertux/tile_set_parser.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,11 @@ class TileSetParser final
3838
public:
3939
TileSetParser(TileSet& tileset, const std::string& filename);
4040

41-
void parse();
41+
void parse(int32_t start = 0, int32_t end = 0, int32_t offset = 0, bool imported = false);
4242

4343
private:
44-
void parse_tile(const ReaderMapping& reader);
45-
void parse_tiles(const ReaderMapping& reader);
44+
void parse_tile(const ReaderMapping& reader, int32_t min, int32_t max, int32_t offset);
45+
void parse_tiles(const ReaderMapping& reader, int32_t min, int32_t max, int32_t offset);
4646
std::vector<SurfacePtr> parse_imagespecs(const ReaderMapping& cur,
4747
const boost::optional<Rect>& region = boost::none) const;
4848

0 commit comments

Comments
 (0)