Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/utility/fix_embedded_tilesets.cpp
diff options
context:
space:
mode:
authorKae <80987908+Novaenia@users.noreply.github.com>2023-06-20 14:33:09 +1000
committerKae <80987908+Novaenia@users.noreply.github.com>2023-06-20 14:33:09 +1000
commit6352e8e3196f78388b6c771073f9e03eaa612673 (patch)
treee23772f79a7fbc41bc9108951e9e136857484bf4 /source/utility/fix_embedded_tilesets.cpp
parent6741a057e5639280d85d0f88ba26f000baa58f61 (diff)
everything everywhere
all at once
Diffstat (limited to 'source/utility/fix_embedded_tilesets.cpp')
-rw-r--r--source/utility/fix_embedded_tilesets.cpp101
1 files changed, 101 insertions, 0 deletions
diff --git a/source/utility/fix_embedded_tilesets.cpp b/source/utility/fix_embedded_tilesets.cpp
new file mode 100644
index 0000000..262426d
--- /dev/null
+++ b/source/utility/fix_embedded_tilesets.cpp
@@ -0,0 +1,101 @@
+#include "StarFile.hpp"
+#include "StarLogging.hpp"
+#include "StarRootLoader.hpp"
+#include "StarTilesetDatabase.hpp"
+
+using namespace Star;
+
+void removeCommonPrefix(StringList& a, StringList& b) {
+ // Remove elements from a and b until there is one that differs.
+ while (a.size() > 0 && b.size() > 0 && a[0] == b[0]) {
+ a.eraseAt(0);
+ b.eraseAt(0);
+ }
+}
+
+String createRelativePath(String fromFile, String toFile) {
+ if (!File::isDirectory(fromFile))
+ fromFile = File::dirName(fromFile);
+ fromFile = File::fullPath(fromFile);
+ toFile = File::fullPath(toFile);
+
+ StringList fromParts = fromFile.splitAny("/\\");
+ StringList toParts = toFile.splitAny("/\\");
+ removeCommonPrefix(fromParts, toParts);
+
+ StringList relativeParts;
+ for (String part : fromParts)
+ relativeParts.append("..");
+ relativeParts.appendAll(toParts);
+
+ return relativeParts.join("/");
+}
+
+Maybe<Json> repairTileset(Json tileset, String const& mapPath, String const& tilesetPath) {
+ if (tileset.contains("source"))
+ return {};
+ size_t firstGid = tileset.getUInt("firstgid");
+ String tilesetName = tileset.getString("name");
+ String tilesetFileName = File::relativeTo(tilesetPath, tilesetName + ".json");
+ if (!File::exists(tilesetFileName))
+ throw StarException::format("Tileset %s does not exist. Can't repair %s", tilesetFileName, mapPath);
+ return {JsonObject{{"firstgid", firstGid}, {"source", createRelativePath(mapPath, tilesetFileName)}}};
+}
+
+Maybe<Json> repair(Json mapJson, String const& mapPath, String const& tilesetPath) {
+ JsonArray tilesets = mapJson.getArray("tilesets");
+ bool changed = false;
+ for (size_t i = 0; i < tilesets.size(); ++i) {
+ if (Maybe<Json> tileset = repairTileset(tilesets[i], mapPath, tilesetPath)) {
+ tilesets[i] = *tileset;
+ changed = true;
+ }
+ }
+ if (!changed)
+ return {};
+ return mapJson.set("tilesets", tilesets);
+}
+
+void forEachRecursiveFileMatch(String const& dirName, String const& filenameSuffix, function<void(String)> func) {
+ for (pair<String, bool> entry : File::dirList(dirName)) {
+ if (entry.second)
+ forEachRecursiveFileMatch(File::relativeTo(dirName, entry.first), filenameSuffix, func);
+ else if (entry.first.endsWith(filenameSuffix))
+ func(File::relativeTo(dirName, entry.first));
+ }
+}
+
+void fixEmbeddedTilesets(String const& searchRoot, String const& tilesetPath) {
+ forEachRecursiveFileMatch(searchRoot, ".json", [tilesetPath](String const& path) {
+ Json json = Json::parseJson(File::readFileString(path));
+ if (json.contains("tilesets")) {
+ if (Maybe<Json> fixed = repair(json, path, tilesetPath)) {
+ File::writeFile(fixed->repr(2, true), path);
+ Logger::info("Repaired %s", path);
+ }
+ }
+ });
+}
+
+int main(int argc, char* argv[]) {
+ try {
+ RootLoader rootLoader({{}, {}, {}, LogLevel::Info, false, {}});
+ rootLoader.setSummary("Replaces embedded tilesets in Tiled JSON files with references to external tilesets. Assumes tilesets are available in the packed assets.");
+ rootLoader.addArgument("searchRoot", OptionParser::Required);
+ rootLoader.addArgument("tilesetsPath", OptionParser::Required);
+
+ RootUPtr root;
+ OptionParser::Options options;
+ tie(root, options) = rootLoader.commandInitOrDie(argc, argv);
+
+ String searchRoot = options.arguments[0];
+ String tilesetPath = options.arguments[1];
+
+ fixEmbeddedTilesets(searchRoot, tilesetPath);
+
+ return 0;
+ } catch (std::exception const& e) {
+ cerrf("exception caught: %s\n", outputException(e, true));
+ return 1;
+ }
+}