git repos / saland

commit 6e0560d4

Poul Sander · 2026-05-09 11:10
6e0560d499319bb33f9d16412ef2452cff9d0ee2 patch · browse files
parent ef2a612a737b2ec74588537d9656f607dc0d394a

Add ensure tileset feature

Changed files

M src/saland/GameRegion.cpp before
diff --git a/src/saland/GameRegion.cpp b/src/saland/GameRegion.cpp index 9a2da40..d7da382 100644 --- a/src/saland/GameRegion.cpp +++ b/src/saland/GameRegion.cpp
@@ -323,6 +323,57 @@ void GameRegion::InitCommon() {
world.managed_bodies.clear();
}
+/**
+ * Ensures the named tileset (by short name, without path or .tsx extension) is present in the
+ * TileMap. If it is already loaded nothing happens. If it is missing but the .tsx file exists,
+ * it is loaded and appended to the map's tileset list with the next available firstgid.
+ * This allows old saved maps to gain new tilesets without manual editing.
+ */
+static void ensureTilesetInMap(World& world, const std::string& tsxName) {
+ // Check if already present (quiet — avoids duplicate warning from getFirstGidForTilesetSource)
+ for (const auto& ts : world.tm.tileset) {
+ if (!ts.source.empty()) {
+ std::string basename = ts.source;
+ size_t slash = basename.find_last_of("/\\");
+ if (slash != std::string::npos) {
+ basename = basename.substr(slash + 1);
+ }
+ size_t dot = basename.rfind('.');
+ if (dot != std::string::npos) {
+ basename = basename.substr(0, dot);
+ }
+ if (basename == tsxName) {
+ return; // already present
+ }
+ }
+ }
+ std::string tsxPath = "maps/" + tsxName + ".tsx";
+ if (!sago::FileExists(tsxPath.c_str())) {
+ std::cerr << "ensureTilesetInMap: " << tsxPath << " not found in virtual filesystem\n";
+ return;
+ }
+ // Compute next available firstgid (max of firstgid + tilecount for each existing tileset)
+ int next_firstgid = 1;
+ for (const auto& ts : world.tm.tileset) {
+ const sago::tiled::TileSet* effective = &ts;
+ while (effective->alternativeSource) {
+ effective = effective->alternativeSource;
+ }
+ int end_gid = ts.firstgid + (effective->tilecount > 0 ? effective->tilecount : 1024);
+ if (end_gid > next_firstgid) {
+ next_firstgid = end_gid;
+ }
+ }
+ std::string tsx_content = sago::GetFileContent(tsxPath.c_str());
+ world.ts.push_back(sago::tiled::string2tileset(tsx_content));
+ sago::tiled::TileSet map_entry;
+ map_entry.firstgid = next_firstgid;
+ map_entry.source = tsxName + ".tsx";
+ map_entry.alternativeSource = &world.ts.back();
+ world.tm.tileset.push_back(map_entry);
+ std::cout << "Dynamically loaded tileset '" << tsxName << "' at firstgid=" << next_firstgid << "\n";
+}
+
void GameRegion::InitLiquidHandlers() {
liqudHandler.clear();
@@ -344,6 +395,7 @@ void GameRegion::InitLiquidHandlers() {
liqudHandler["ground"].blockingLayer_overlay_1 = world.ground2OverlayLayer;
liqudHandler["ground"].setupTiles(terrain_firstgid + 0, terrain_cols);
+ ensureTilesetInMap(world, "tiles_dungeon");
uint32_t dungeon_firstgid = sago::tiled::getFirstGidForTilesetSource(world.tm, "tiles_dungeon");
if (dungeon_firstgid > 0) {
int dungeon_cols = sago::tiled::getTilesetColumns(world.tm, "tiles_dungeon");