mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-07 09:33:51 +00:00
feat(editor): add --info-textures and --info-doodads detailed inspectors
Two more drill-down inspectors that complement --info-batches:
wowee_editor --info-textures HumanMale.wom
WOM textures: HumanMale.wom (3 textures)
idx blp png path
0 y y Character/Human/Male/HumanMaleHair.blp
1 y - Character/Human/Male/HumanMaleBody.blp
2 - - Character/Human/Male/HumanMaleEye.blp
wowee_editor --info-doodads Stormwind.wob
WOB doodads: Stormwind.wob (3 placements)
idx scale pos (x, y, z) rot (x, y, z) model
0 1.50 ( 1.0, 0.0, 1.0) ( 0.0, 90.0, 0.0) Furniture/Chair.wom
...
--info-textures: cross-checks each referenced texture against both
the proprietary BLP and the open PNG sidecar on disk (each lookup
tries the literal path AND falls back to Data/<lowercased path>
since WoW assets are case-sensitive on Linux but designers usually
type Mixed Case). The y/- columns let you spot which textures are
missing before --pack-wcp would fail at runtime.
--info-doodads: model path + position + rotation + scale per
instance. Companion to --info-textures (GPU resources) — this tracks
scene composition.
Both have --json mode that emits per-entry records with index for
programmatic consumption. Verified on synthesized model with 3
texture refs + building with 3 doodads; all fields render correctly.
This commit is contained in:
parent
ac096c5c86
commit
82987af460
1 changed files with 135 additions and 1 deletions
|
|
@ -496,6 +496,10 @@ static void printUsage(const char* argv0) {
|
|||
std::printf(" Print WOM file metadata (version, counts) and exit\n");
|
||||
std::printf(" --info-batches <wom-base> [--json]\n");
|
||||
std::printf(" Per-batch breakdown of a WOM3 (index range, texture, blend mode, flags)\n");
|
||||
std::printf(" --info-textures <wom-base> [--json]\n");
|
||||
std::printf(" List every texture path referenced by a WOM (with on-disk presence)\n");
|
||||
std::printf(" --info-doodads <wob-base> [--json]\n");
|
||||
std::printf(" List every doodad placement in a WOB (model path, position, rotation, scale)\n");
|
||||
std::printf(" --info-wob <wob-base> [--json]\n");
|
||||
std::printf(" Print WOB building metadata (groups, portals, doodads) and exit\n");
|
||||
std::printf(" --info-woc <woc-path> [--json]\n");
|
||||
|
|
@ -558,7 +562,8 @@ int main(int argc, char* argv[]) {
|
|||
// Detect non-GUI options that are missing their argument and bail out
|
||||
// with a helpful message instead of silently dropping into the GUI.
|
||||
static const char* kArgRequired[] = {
|
||||
"--data", "--info", "--info-batches", "--info-wob", "--info-woc", "--info-wot",
|
||||
"--data", "--info", "--info-batches", "--info-textures", "--info-doodads",
|
||||
"--info-wob", "--info-woc", "--info-wot",
|
||||
"--info-creatures", "--info-objects", "--info-quests",
|
||||
"--info-extract", "--list-missing-sidecars",
|
||||
"--info-png", "--info-jsondbc", "--info-blp",
|
||||
|
|
@ -822,6 +827,135 @@ int main(int argc, char* argv[]) {
|
|||
tex.c_str());
|
||||
}
|
||||
return 0;
|
||||
} else if (std::strcmp(argv[i], "--info-textures") == 0 && i + 1 < argc) {
|
||||
// List every texture path a WOM references, with on-disk
|
||||
// presence for both BLP (proprietary) and PNG (sidecar)
|
||||
// forms. Useful for tracking which textures are missing
|
||||
// before --pack-wcp would fail at runtime.
|
||||
std::string base = argv[++i];
|
||||
bool jsonOut = (i + 1 < argc &&
|
||||
std::strcmp(argv[i + 1], "--json") == 0);
|
||||
if (jsonOut) i++;
|
||||
if (base.size() >= 4 && base.substr(base.size() - 4) == ".wom")
|
||||
base = base.substr(0, base.size() - 4);
|
||||
if (!wowee::pipeline::WoweeModelLoader::exists(base)) {
|
||||
std::fprintf(stderr, "WOM not found: %s.wom\n", base.c_str());
|
||||
return 1;
|
||||
}
|
||||
auto wom = wowee::pipeline::WoweeModelLoader::load(base);
|
||||
namespace fs = std::filesystem;
|
||||
// Texture paths in WOMs are usually game-relative
|
||||
// ('World/Generic/Tree.blp'); resolve them against the
|
||||
// common Data/ root for the on-disk presence check. Skip
|
||||
// the check when the path doesn't exist as either an
|
||||
// absolute or relative file (avoids false 'missing'
|
||||
// reports when the user runs from outside the data root).
|
||||
auto checkBlp = [&](const std::string& p) {
|
||||
if (fs::exists(p)) return true;
|
||||
std::string lower = p;
|
||||
for (auto& c : lower) c = std::tolower(static_cast<unsigned char>(c));
|
||||
if (lower.size() < 4 || lower.substr(lower.size() - 4) != ".blp") {
|
||||
lower += ".blp";
|
||||
}
|
||||
return fs::exists("Data/" + lower);
|
||||
};
|
||||
auto sidecarPng = [&](const std::string& p) {
|
||||
std::string base = p;
|
||||
if (base.size() >= 4 &&
|
||||
(base.substr(base.size() - 4) == ".blp" ||
|
||||
base.substr(base.size() - 4) == ".BLP")) {
|
||||
base = base.substr(0, base.size() - 4);
|
||||
}
|
||||
std::string png = base + ".png";
|
||||
if (fs::exists(png)) return true;
|
||||
std::string lower = png;
|
||||
for (auto& c : lower) c = std::tolower(static_cast<unsigned char>(c));
|
||||
return fs::exists("Data/" + lower);
|
||||
};
|
||||
if (jsonOut) {
|
||||
nlohmann::json j;
|
||||
j["wom"] = base + ".wom";
|
||||
j["textureCount"] = wom.texturePaths.size();
|
||||
nlohmann::json arr = nlohmann::json::array();
|
||||
for (size_t k = 0; k < wom.texturePaths.size(); ++k) {
|
||||
const auto& p = wom.texturePaths[k];
|
||||
arr.push_back({
|
||||
{"index", k},
|
||||
{"path", p},
|
||||
{"blpPresent", checkBlp(p)},
|
||||
{"pngPresent", sidecarPng(p)},
|
||||
});
|
||||
}
|
||||
j["textures"] = arr;
|
||||
std::printf("%s\n", j.dump(2).c_str());
|
||||
return 0;
|
||||
}
|
||||
std::printf("WOM textures: %s.wom (%zu textures)\n",
|
||||
base.c_str(), wom.texturePaths.size());
|
||||
if (wom.texturePaths.empty()) {
|
||||
std::printf(" *no texture references*\n");
|
||||
return 0;
|
||||
}
|
||||
std::printf(" idx blp png path\n");
|
||||
for (size_t k = 0; k < wom.texturePaths.size(); ++k) {
|
||||
const auto& p = wom.texturePaths[k];
|
||||
std::printf(" %3zu %s %s %s\n",
|
||||
k,
|
||||
checkBlp(p) ? "y" : "-",
|
||||
sidecarPng(p) ? "y" : "-",
|
||||
p.c_str());
|
||||
}
|
||||
return 0;
|
||||
} else if (std::strcmp(argv[i], "--info-doodads") == 0 && i + 1 < argc) {
|
||||
// List every doodad placement in a WOB (M2 instances inside
|
||||
// a building). Companion to --info-textures: where one
|
||||
// tracks GPU resources, this tracks scene composition.
|
||||
std::string base = argv[++i];
|
||||
bool jsonOut = (i + 1 < argc &&
|
||||
std::strcmp(argv[i + 1], "--json") == 0);
|
||||
if (jsonOut) i++;
|
||||
if (base.size() >= 4 && base.substr(base.size() - 4) == ".wob")
|
||||
base = base.substr(0, base.size() - 4);
|
||||
if (!wowee::pipeline::WoweeBuildingLoader::exists(base)) {
|
||||
std::fprintf(stderr, "WOB not found: %s.wob\n", base.c_str());
|
||||
return 1;
|
||||
}
|
||||
auto bld = wowee::pipeline::WoweeBuildingLoader::load(base);
|
||||
if (jsonOut) {
|
||||
nlohmann::json j;
|
||||
j["wob"] = base + ".wob";
|
||||
j["count"] = bld.doodads.size();
|
||||
nlohmann::json arr = nlohmann::json::array();
|
||||
for (size_t k = 0; k < bld.doodads.size(); ++k) {
|
||||
const auto& d = bld.doodads[k];
|
||||
arr.push_back({
|
||||
{"index", k},
|
||||
{"modelPath", d.modelPath},
|
||||
{"position", {d.position.x, d.position.y, d.position.z}},
|
||||
{"rotation", {d.rotation.x, d.rotation.y, d.rotation.z}},
|
||||
{"scale", d.scale},
|
||||
});
|
||||
}
|
||||
j["doodads"] = arr;
|
||||
std::printf("%s\n", j.dump(2).c_str());
|
||||
return 0;
|
||||
}
|
||||
std::printf("WOB doodads: %s.wob (%zu placements)\n",
|
||||
base.c_str(), bld.doodads.size());
|
||||
if (bld.doodads.empty()) {
|
||||
std::printf(" *no doodad placements*\n");
|
||||
return 0;
|
||||
}
|
||||
std::printf(" idx scale pos (x, y, z) rot (x, y, z) model\n");
|
||||
for (size_t k = 0; k < bld.doodads.size(); ++k) {
|
||||
const auto& d = bld.doodads[k];
|
||||
std::printf(" %3zu %5.2f (%6.1f, %6.1f, %6.1f) (%6.1f, %6.1f, %6.1f) %s\n",
|
||||
k, d.scale,
|
||||
d.position.x, d.position.y, d.position.z,
|
||||
d.rotation.x, d.rotation.y, d.rotation.z,
|
||||
d.modelPath.c_str());
|
||||
}
|
||||
return 0;
|
||||
} else if (std::strcmp(argv[i], "--info-wob") == 0 && i + 1 < argc) {
|
||||
std::string base = argv[++i];
|
||||
bool jsonOut = (i + 1 < argc &&
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue