mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-08 01:53:52 +00:00
feat(editor): add --info-project-extents for combined spatial bbox
Project-wide companion to --info-zone-extents. Walks every zone in <projectDir>, computes each zone's tile XY range and Z height range, then unions them into a project-wide world bounding box. Per-zone breakdown table shows each zone's disjoint world ranges so overlap issues are visible at a glance. Useful for sizing the world map overview, sanity-checking that zones don't overlap (project-union should equal sum of per-zone areas for disjoint layouts), and understanding total project area in both yards and meters. Verified on 2-zone test project: each zone correctly resolves to one 533x533yd tile, project union is 1066x533yd (the two tiles arranged horizontally), Z range matches manifest baseHeight + heightmap delta. Brings command count to 178.
This commit is contained in:
parent
14492abc99
commit
439cd943e4
1 changed files with 142 additions and 1 deletions
|
|
@ -684,6 +684,8 @@ static void printUsage(const char* argv0) {
|
|||
std::printf(" Run validate-project + open-only + check-project-refs together; one PASS/FAIL\n");
|
||||
std::printf(" --info-zone-bytes <zoneDir> [--json]\n");
|
||||
std::printf(" Per-file size breakdown grouped by category, sorted largest-first\n");
|
||||
std::printf(" --info-project-extents <projectDir> [--json]\n");
|
||||
std::printf(" Combined spatial bounding box across every zone (per-zone table + project union)\n");
|
||||
std::printf(" --info-zone-extents <zoneDir> [--json]\n");
|
||||
std::printf(" Compute the zone's bounding box (XY tile range, Z height min/max)\n");
|
||||
std::printf(" --info-zone-water <zoneDir> [--json]\n");
|
||||
|
|
@ -879,7 +881,8 @@ int main(int argc, char* argv[]) {
|
|||
"--validate-png", "--validate-blp",
|
||||
"--zone-summary", "--info-zone-tree", "--info-project-tree",
|
||||
"--info-zone-bytes", "--info-project-bytes",
|
||||
"--info-zone-extents", "--info-zone-water",
|
||||
"--info-zone-extents", "--info-project-extents",
|
||||
"--info-zone-water",
|
||||
"--info-zone-density",
|
||||
"--export-zone-summary-md", "--export-quest-graph",
|
||||
"--export-zone-csv", "--export-zone-html", "--export-project-html",
|
||||
|
|
@ -5871,6 +5874,144 @@ int main(int argc, char* argv[]) {
|
|||
widthX, widthY, heightZ,
|
||||
widthX * 0.9144f, widthY * 0.9144f, heightZ * 0.9144f);
|
||||
return 0;
|
||||
} else if (std::strcmp(argv[i], "--info-project-extents") == 0 && i + 1 < argc) {
|
||||
// Combined spatial bounding box across every zone in
|
||||
// <projectDir>. Per-zone XY tile range + Z height range,
|
||||
// unioned into a project-wide world box. Useful for
|
||||
// understanding total project area, sizing the world map
|
||||
// overview, or sanity-checking that zones don't overlap
|
||||
// (the union should equal the sum of disjoint per-zone
|
||||
// boxes).
|
||||
std::string projectDir = argv[++i];
|
||||
bool jsonOut = (i + 1 < argc &&
|
||||
std::strcmp(argv[i + 1], "--json") == 0);
|
||||
if (jsonOut) i++;
|
||||
namespace fs = std::filesystem;
|
||||
if (!fs::exists(projectDir) || !fs::is_directory(projectDir)) {
|
||||
std::fprintf(stderr,
|
||||
"info-project-extents: %s is not a directory\n",
|
||||
projectDir.c_str());
|
||||
return 1;
|
||||
}
|
||||
std::vector<std::string> zones;
|
||||
for (const auto& entry : fs::directory_iterator(projectDir)) {
|
||||
if (!entry.is_directory()) continue;
|
||||
if (!fs::exists(entry.path() / "zone.json")) continue;
|
||||
zones.push_back(entry.path().string());
|
||||
}
|
||||
std::sort(zones.begin(), zones.end());
|
||||
constexpr float kTileSize = 533.33333f;
|
||||
struct ZBox {
|
||||
std::string name;
|
||||
int tileCount = 0;
|
||||
float wMinX = 1e30f, wMaxX = -1e30f;
|
||||
float wMinY = 1e30f, wMaxY = -1e30f;
|
||||
float zMin = 1e30f, zMax = -1e30f;
|
||||
};
|
||||
std::vector<ZBox> rows;
|
||||
float gMinX = 1e30f, gMaxX = -1e30f;
|
||||
float gMinY = 1e30f, gMaxY = -1e30f;
|
||||
float gZMin = 1e30f, gZMax = -1e30f;
|
||||
int totalTiles = 0;
|
||||
for (const auto& zoneDir : zones) {
|
||||
ZBox b;
|
||||
b.name = fs::path(zoneDir).filename().string();
|
||||
wowee::editor::ZoneManifest zm;
|
||||
if (!zm.load(zoneDir + "/zone.json")) {
|
||||
rows.push_back(b);
|
||||
continue;
|
||||
}
|
||||
b.tileCount = static_cast<int>(zm.tiles.size());
|
||||
if (zm.tiles.empty()) {
|
||||
rows.push_back(b);
|
||||
continue;
|
||||
}
|
||||
int tMinX = 64, tMaxX = -1, tMinY = 64, tMaxY = -1;
|
||||
for (const auto& [tx, ty] : zm.tiles) {
|
||||
tMinX = std::min(tMinX, tx);
|
||||
tMaxX = std::max(tMaxX, tx);
|
||||
tMinY = std::min(tMinY, ty);
|
||||
tMaxY = std::max(tMaxY, ty);
|
||||
}
|
||||
b.wMinX = (32.0f - tMaxY - 1) * kTileSize;
|
||||
b.wMaxX = (32.0f - tMinY) * kTileSize;
|
||||
b.wMinY = (32.0f - tMaxX - 1) * kTileSize;
|
||||
b.wMaxY = (32.0f - tMinX) * kTileSize;
|
||||
for (const auto& [tx, ty] : zm.tiles) {
|
||||
std::string tileBase = zoneDir + "/" + zm.mapName + "_" +
|
||||
std::to_string(tx) + "_" + std::to_string(ty);
|
||||
if (!wowee::pipeline::WoweeTerrainLoader::exists(tileBase)) continue;
|
||||
wowee::pipeline::ADTTerrain terrain;
|
||||
wowee::pipeline::WoweeTerrainLoader::load(tileBase, terrain);
|
||||
for (const auto& chunk : terrain.chunks) {
|
||||
if (!chunk.heightMap.isLoaded()) continue;
|
||||
float baseZ = chunk.position[2];
|
||||
for (float h : chunk.heightMap.heights) {
|
||||
if (!std::isfinite(h)) continue;
|
||||
b.zMin = std::min(b.zMin, baseZ + h);
|
||||
b.zMax = std::max(b.zMax, baseZ + h);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (b.zMin > b.zMax) { b.zMin = 0; b.zMax = 0; }
|
||||
gMinX = std::min(gMinX, b.wMinX);
|
||||
gMaxX = std::max(gMaxX, b.wMaxX);
|
||||
gMinY = std::min(gMinY, b.wMinY);
|
||||
gMaxY = std::max(gMaxY, b.wMaxY);
|
||||
gZMin = std::min(gZMin, b.zMin);
|
||||
gZMax = std::max(gZMax, b.zMax);
|
||||
totalTiles += b.tileCount;
|
||||
rows.push_back(b);
|
||||
}
|
||||
if (totalTiles == 0) {
|
||||
gMinX = gMaxX = gMinY = gMaxY = gZMin = gZMax = 0.0f;
|
||||
}
|
||||
float gWidthX = gMaxX - gMinX;
|
||||
float gWidthY = gMaxY - gMinY;
|
||||
float gHeightZ = gZMax - gZMin;
|
||||
if (jsonOut) {
|
||||
nlohmann::json j;
|
||||
j["project"] = projectDir;
|
||||
j["zoneCount"] = zones.size();
|
||||
j["totalTiles"] = totalTiles;
|
||||
j["worldBox"] = {{"min", {gMinX, gMinY, gZMin}},
|
||||
{"max", {gMaxX, gMaxY, gZMax}}};
|
||||
j["sizeYards"] = {gWidthX, gWidthY, gHeightZ};
|
||||
nlohmann::json zarr = nlohmann::json::array();
|
||||
for (const auto& b : rows) {
|
||||
zarr.push_back({{"name", b.name},
|
||||
{"tileCount", b.tileCount},
|
||||
{"worldBox", {{"min", {b.wMinX, b.wMinY, b.zMin}},
|
||||
{"max", {b.wMaxX, b.wMaxY, b.zMax}}}}});
|
||||
}
|
||||
j["zones"] = zarr;
|
||||
std::printf("%s\n", j.dump(2).c_str());
|
||||
return 0;
|
||||
}
|
||||
std::printf("Project extents: %s\n", projectDir.c_str());
|
||||
std::printf(" zones : %zu\n", zones.size());
|
||||
std::printf(" total tiles : %d\n", totalTiles);
|
||||
if (totalTiles == 0) {
|
||||
std::printf(" *no tiles in any zone manifest*\n");
|
||||
return 0;
|
||||
}
|
||||
std::printf(" world union : (%.1f, %.1f, %.1f) - (%.1f, %.1f, %.1f) yards\n",
|
||||
gMinX, gMinY, gZMin, gMaxX, gMaxY, gZMax);
|
||||
std::printf(" total size : %.1f x %.1f x %.1f yards (%.0fm x %.0fm x %.1fm)\n",
|
||||
gWidthX, gWidthY, gHeightZ,
|
||||
gWidthX * 0.9144f, gWidthY * 0.9144f, gHeightZ * 0.9144f);
|
||||
std::printf("\n zone tiles worldX (min..max) worldY (min..max)\n");
|
||||
for (const auto& b : rows) {
|
||||
if (b.tileCount == 0) {
|
||||
std::printf(" %-20s %5d (no tiles)\n",
|
||||
b.name.substr(0, 20).c_str(), b.tileCount);
|
||||
continue;
|
||||
}
|
||||
std::printf(" %-20s %5d %9.1f .. %9.1f %9.1f .. %9.1f\n",
|
||||
b.name.substr(0, 20).c_str(), b.tileCount,
|
||||
b.wMinX, b.wMaxX, b.wMinY, b.wMaxY);
|
||||
}
|
||||
return 0;
|
||||
} else if (std::strcmp(argv[i], "--info-zone-water") == 0 && i + 1 < argc) {
|
||||
// Aggregate water-layer stats across all tiles in a zone.
|
||||
// Useful for confirming a 'lake zone' actually has water,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue