mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-09 02:23:52 +00:00
refactor(editor): extract zone-pack orchestrators into cli_zone_packs.cpp
Continues the modularization started in 6c9ab6fa. Moves the four
pack-orchestrator handlers (--gen-zone-texture-pack, -mesh-pack,
-starter-pack, --gen-project-starter-pack) into their own file
following the same handle<Family> pattern.
Side cleanup:
- Consolidated the duplicated --seed flag parser into a single
parseSeedFlag helper
- Consolidated the std::system + > /dev/null wrap into runSilently
main.cpp drops 28,329 → 28,070 lines (-259). Pack family is fully
self-contained (~260 lines), behavior unchanged (verified by
re-running gen-zone-starter-pack and confirming 6 PNGs + 5 WOMs).
This commit is contained in:
parent
6c9ab6faed
commit
774dab9330
4 changed files with 302 additions and 263 deletions
|
|
@ -1299,6 +1299,7 @@ install(TARGETS blp_convert RUNTIME DESTINATION bin)
|
|||
add_executable(wowee_editor
|
||||
tools/editor/main.cpp
|
||||
tools/editor/cli_gen_audio.cpp
|
||||
tools/editor/cli_zone_packs.cpp
|
||||
tools/editor/editor_app.cpp
|
||||
tools/editor/editor_camera.cpp
|
||||
tools/editor/editor_viewport.cpp
|
||||
|
|
|
|||
275
tools/editor/cli_zone_packs.cpp
Normal file
275
tools/editor/cli_zone_packs.cpp
Normal file
|
|
@ -0,0 +1,275 @@
|
|||
#include "cli_zone_packs.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace wowee {
|
||||
namespace editor {
|
||||
namespace cli {
|
||||
|
||||
namespace {
|
||||
|
||||
// Parse a trailing `--seed N` flag pair. Returns updated `i` past
|
||||
// the consumed args via the by-ref param. Sets seed if found.
|
||||
// Returns false if it sees an unknown --flag (caller should error).
|
||||
bool parseSeedFlag(int& i, int argc, char** argv,
|
||||
const char* cmdName, uint32_t& seed) {
|
||||
for (int k = i + 1; k < argc; ++k) {
|
||||
std::string flag = argv[k];
|
||||
if (flag == "--seed" && k + 1 < argc) {
|
||||
try { seed = static_cast<uint32_t>(std::stoul(argv[++k])); }
|
||||
catch (...) {}
|
||||
i = k;
|
||||
} else if (flag.rfind("--", 0) == 0) {
|
||||
std::fprintf(stderr,
|
||||
"%s: unknown flag '%s'\n", cmdName, flag.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Run a sub-process via std::system, log on failure, return rc==0.
|
||||
bool runSilently(const std::string& cmd) {
|
||||
std::string full = cmd + " > /dev/null 2>&1";
|
||||
return std::system(full.c_str()) == 0;
|
||||
}
|
||||
|
||||
int handleTexturePack(int& i, int argc, char** argv) {
|
||||
// Drop a starter PNG texture pack into <zoneDir>/textures/
|
||||
// by fanning out to the procedural --gen-texture-* commands.
|
||||
// Saves the user from sourcing proprietary art when bringing
|
||||
// up a new zone — six themed textures cover most needs.
|
||||
std::string zoneDir = argv[++i];
|
||||
uint32_t seed = 1;
|
||||
if (!parseSeedFlag(i, argc, argv, "gen-zone-texture-pack", seed)) return 1;
|
||||
std::filesystem::path zp(zoneDir);
|
||||
if (!std::filesystem::exists(zp / "zone.json")) {
|
||||
std::fprintf(stderr,
|
||||
"gen-zone-texture-pack: %s has no zone.json\n", zoneDir.c_str());
|
||||
return 1;
|
||||
}
|
||||
std::filesystem::path texDir = zp / "textures";
|
||||
std::error_code ec;
|
||||
std::filesystem::create_directories(texDir, ec);
|
||||
if (ec) {
|
||||
std::fprintf(stderr,
|
||||
"gen-zone-texture-pack: cannot create %s: %s\n",
|
||||
texDir.string().c_str(), ec.message().c_str());
|
||||
return 1;
|
||||
}
|
||||
std::string self = (argc > 0) ? argv[0] : "wowee_editor";
|
||||
struct Cmd {
|
||||
std::string flag;
|
||||
std::string outName;
|
||||
std::vector<std::string> args;
|
||||
};
|
||||
std::vector<Cmd> jobs = {
|
||||
{"--gen-texture-noise", "grass.png", {"4A7C2E", "5C9B3A", "256", "256"}},
|
||||
{"--gen-texture-noise", "dirt.png", {"6B4A2A", "8B5E3A", "256", "256"}},
|
||||
{"--gen-texture-checker", "stone.png", {"7A7A7A", "5A5A5A", "32", "256", "256"}},
|
||||
{"--gen-texture-brick", "brick.png", {"8B4513", "D3D3D3", "64", "24", "4", "256", "256"}},
|
||||
{"--gen-texture-wood", "wood.png", {"8B5A2B", "4A3216", "12", std::to_string(seed), "256", "256"}},
|
||||
{"--gen-texture-radial", "water.png", {"3A6FA0", "1E4A78", "256", "256"}},
|
||||
};
|
||||
int written = 0;
|
||||
for (const auto& job : jobs) {
|
||||
std::filesystem::path out = texDir / job.outName;
|
||||
std::string cmd = "\"" + self + "\" " + job.flag + " \"" + out.string() + "\"";
|
||||
for (const auto& a : job.args) cmd += " " + a;
|
||||
if (!runSilently(cmd)) {
|
||||
std::fprintf(stderr,
|
||||
"gen-zone-texture-pack: %s failed\n", job.flag.c_str());
|
||||
} else {
|
||||
++written;
|
||||
}
|
||||
}
|
||||
std::printf("gen-zone-texture-pack: wrote %d of %zu textures to %s\n",
|
||||
written, jobs.size(), texDir.string().c_str());
|
||||
return written == static_cast<int>(jobs.size()) ? 0 : 1;
|
||||
}
|
||||
|
||||
int handleMeshPack(int& i, int argc, char** argv) {
|
||||
// Companion to --gen-zone-texture-pack: drops a starter
|
||||
// WOM mesh pack into <zoneDir>/meshes/. Each rock variant
|
||||
// uses a different seed so they read as distinct boulders.
|
||||
std::string zoneDir = argv[++i];
|
||||
uint32_t seed = 1;
|
||||
if (!parseSeedFlag(i, argc, argv, "gen-zone-mesh-pack", seed)) return 1;
|
||||
std::filesystem::path zp(zoneDir);
|
||||
if (!std::filesystem::exists(zp / "zone.json")) {
|
||||
std::fprintf(stderr,
|
||||
"gen-zone-mesh-pack: %s has no zone.json\n", zoneDir.c_str());
|
||||
return 1;
|
||||
}
|
||||
std::filesystem::path meshDir = zp / "meshes";
|
||||
std::error_code ec;
|
||||
std::filesystem::create_directories(meshDir, ec);
|
||||
if (ec) {
|
||||
std::fprintf(stderr,
|
||||
"gen-zone-mesh-pack: cannot create %s: %s\n",
|
||||
meshDir.string().c_str(), ec.message().c_str());
|
||||
return 1;
|
||||
}
|
||||
std::string self = (argc > 0) ? argv[0] : "wowee_editor";
|
||||
struct MeshJob {
|
||||
std::string flag;
|
||||
std::string outBase; // no .wom extension
|
||||
std::vector<std::string> args;
|
||||
};
|
||||
std::string s0 = std::to_string(seed);
|
||||
std::string s1 = std::to_string(seed + 17);
|
||||
std::string s2 = std::to_string(seed + 41);
|
||||
std::vector<MeshJob> jobs = {
|
||||
// 3 rock variants with distinct seeds for variety
|
||||
{"--gen-mesh-rock", "rock_small", {"0.6", "0.30", "2", s0}},
|
||||
{"--gen-mesh-rock", "rock_medium", {"1.2", "0.25", "2", s1}},
|
||||
{"--gen-mesh-rock", "rock_large", {"2.4", "0.35", "3", s2}},
|
||||
// Tree placeholder, fence segment for boundaries
|
||||
{"--gen-mesh-tree", "tree", {"0.15", "3.0", "1.0"}},
|
||||
{"--gen-mesh-fence", "fence", {"5", "1.2", "1.4", "0.06"}},
|
||||
};
|
||||
int written = 0;
|
||||
for (const auto& job : jobs) {
|
||||
std::filesystem::path out = meshDir / job.outBase;
|
||||
std::string cmd = "\"" + self + "\" " + job.flag + " \"" + out.string() + "\"";
|
||||
for (const auto& a : job.args) cmd += " " + a;
|
||||
if (!runSilently(cmd)) {
|
||||
std::fprintf(stderr,
|
||||
"gen-zone-mesh-pack: %s failed\n", job.flag.c_str());
|
||||
} else {
|
||||
++written;
|
||||
}
|
||||
}
|
||||
std::printf("gen-zone-mesh-pack: wrote %d of %zu meshes to %s\n",
|
||||
written, jobs.size(), meshDir.string().c_str());
|
||||
return written == static_cast<int>(jobs.size()) ? 0 : 1;
|
||||
}
|
||||
|
||||
int handleZoneStarterPack(int& i, int argc, char** argv) {
|
||||
// Convenience entry point: run --gen-zone-texture-pack
|
||||
// and --gen-zone-mesh-pack in sequence so a fresh zone
|
||||
// gets a full open-format asset bootstrap from a single
|
||||
// command. Seed propagates to both children.
|
||||
std::string zoneDir = argv[++i];
|
||||
uint32_t seed = 1;
|
||||
if (!parseSeedFlag(i, argc, argv, "gen-zone-starter-pack", seed)) return 1;
|
||||
if (!std::filesystem::exists(std::filesystem::path(zoneDir) / "zone.json")) {
|
||||
std::fprintf(stderr,
|
||||
"gen-zone-starter-pack: %s has no zone.json\n", zoneDir.c_str());
|
||||
return 1;
|
||||
}
|
||||
std::string self = (argc > 0) ? argv[0] : "wowee_editor";
|
||||
std::string seedStr = std::to_string(seed);
|
||||
std::printf("gen-zone-starter-pack: %s (seed %u)\n",
|
||||
zoneDir.c_str(), seed);
|
||||
std::printf(" step 1/2: textures\n");
|
||||
std::string cmd1 = "\"" + self + "\" --gen-zone-texture-pack \"" +
|
||||
zoneDir + "\" --seed " + seedStr;
|
||||
if (std::system(cmd1.c_str()) != 0) {
|
||||
std::fprintf(stderr, "gen-zone-starter-pack: texture step failed\n");
|
||||
return 1;
|
||||
}
|
||||
std::printf(" step 2/2: meshes\n");
|
||||
std::string cmd2 = "\"" + self + "\" --gen-zone-mesh-pack \"" +
|
||||
zoneDir + "\" --seed " + seedStr;
|
||||
if (std::system(cmd2.c_str()) != 0) {
|
||||
std::fprintf(stderr, "gen-zone-starter-pack: mesh step failed\n");
|
||||
return 1;
|
||||
}
|
||||
std::printf("\ngen-zone-starter-pack: complete\n");
|
||||
std::printf(" zone dir : %s\n", zoneDir.c_str());
|
||||
std::printf(" textures : 6 PNGs in textures/\n");
|
||||
std::printf(" meshes : 5 WOMs in meshes/\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int handleProjectStarterPack(int& i, int argc, char** argv) {
|
||||
// Project-wide bootstrap. For every zone in <projectDir>,
|
||||
// run --gen-zone-starter-pack (textures + meshes) and
|
||||
// --gen-zone-audio-pack (audio). Each zone gets a unique
|
||||
// sub-seed offset from the base seed so per-zone content
|
||||
// looks distinct.
|
||||
std::string projectDir = argv[++i];
|
||||
uint32_t seed = 1;
|
||||
if (!parseSeedFlag(i, argc, argv, "gen-project-starter-pack", seed)) return 1;
|
||||
namespace fs = std::filesystem;
|
||||
if (!fs::exists(projectDir) || !fs::is_directory(projectDir)) {
|
||||
std::fprintf(stderr,
|
||||
"gen-project-starter-pack: %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());
|
||||
if (zones.empty()) {
|
||||
std::fprintf(stderr,
|
||||
"gen-project-starter-pack: %s contains no zones\n",
|
||||
projectDir.c_str());
|
||||
return 1;
|
||||
}
|
||||
std::string self = (argc > 0) ? argv[0] : "wowee_editor";
|
||||
std::printf("gen-project-starter-pack: %s (base seed %u)\n",
|
||||
projectDir.c_str(), seed);
|
||||
std::printf(" zones: %zu\n\n", zones.size());
|
||||
int passed = 0, failed = 0;
|
||||
for (size_t z = 0; z < zones.size(); ++z) {
|
||||
std::string zoneSeed = std::to_string(seed + z * 17);
|
||||
std::string name = fs::path(zones[z]).filename().string();
|
||||
std::printf(" [%zu/%zu] %s (seed %s)\n",
|
||||
z + 1, zones.size(), name.c_str(), zoneSeed.c_str());
|
||||
std::string c1 = "\"" + self + "\" --gen-zone-starter-pack \"" +
|
||||
zones[z] + "\" --seed " + zoneSeed;
|
||||
bool ok1 = runSilently(c1);
|
||||
std::string c2 = "\"" + self + "\" --gen-zone-audio-pack \"" +
|
||||
zones[z] + "\"";
|
||||
bool ok2 = runSilently(c2);
|
||||
if (ok1 && ok2) {
|
||||
++passed;
|
||||
std::printf(" OK textures + meshes + audio\n");
|
||||
} else {
|
||||
++failed;
|
||||
std::printf(" FAIL starter ok=%d, audio ok=%d\n",
|
||||
static_cast<int>(ok1), static_cast<int>(ok2));
|
||||
}
|
||||
}
|
||||
std::printf("\n Total: %d passed, %d failed\n", passed, failed);
|
||||
return failed == 0 ? 0 : 1;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool handleZonePacks(int& i, int argc, char** argv, int& outRc) {
|
||||
if (std::strcmp(argv[i], "--gen-zone-texture-pack") == 0 && i + 1 < argc) {
|
||||
outRc = handleTexturePack(i, argc, argv);
|
||||
return true;
|
||||
}
|
||||
if (std::strcmp(argv[i], "--gen-zone-mesh-pack") == 0 && i + 1 < argc) {
|
||||
outRc = handleMeshPack(i, argc, argv);
|
||||
return true;
|
||||
}
|
||||
if (std::strcmp(argv[i], "--gen-zone-starter-pack") == 0 && i + 1 < argc) {
|
||||
outRc = handleZoneStarterPack(i, argc, argv);
|
||||
return true;
|
||||
}
|
||||
if (std::strcmp(argv[i], "--gen-project-starter-pack") == 0 && i + 1 < argc) {
|
||||
outRc = handleProjectStarterPack(i, argc, argv);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace cli
|
||||
} // namespace editor
|
||||
} // namespace wowee
|
||||
22
tools/editor/cli_zone_packs.hpp
Normal file
22
tools/editor/cli_zone_packs.hpp
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#pragma once
|
||||
|
||||
namespace wowee {
|
||||
namespace editor {
|
||||
namespace cli {
|
||||
|
||||
// Dispatch the four zone/project pack-orchestrator handlers:
|
||||
// --gen-zone-texture-pack
|
||||
// --gen-zone-mesh-pack
|
||||
// --gen-zone-starter-pack
|
||||
// --gen-project-starter-pack
|
||||
//
|
||||
// Each fans out to per-asset commands via subprocess, so this
|
||||
// module has no dependency on the procedural generators it calls.
|
||||
//
|
||||
// Returns true if matched; outRc holds the exit code. Returns
|
||||
// false if no match — caller should continue its dispatch chain.
|
||||
bool handleZonePacks(int& i, int argc, char** argv, int& outRc);
|
||||
|
||||
} // namespace cli
|
||||
} // namespace editor
|
||||
} // namespace wowee
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
#include "editor_app.hpp"
|
||||
#include "cli_gen_audio.hpp"
|
||||
#include "cli_zone_packs.hpp"
|
||||
#include "content_pack.hpp"
|
||||
#include "npc_spawner.hpp"
|
||||
#include "object_placer.hpp"
|
||||
|
|
@ -1365,6 +1366,9 @@ int main(int argc, char* argv[]) {
|
|||
if (wowee::editor::cli::handleGenAudio(i, argc, argv, outRc)) {
|
||||
return outRc;
|
||||
}
|
||||
if (wowee::editor::cli::handleZonePacks(i, argc, argv, outRc)) {
|
||||
return outRc;
|
||||
}
|
||||
}
|
||||
if (std::strcmp(argv[i], "--data") == 0 && i + 1 < argc) {
|
||||
dataPath = argv[++i];
|
||||
|
|
@ -14397,269 +14401,6 @@ int main(int argc, char* argv[]) {
|
|||
std::printf(" objects : %d\n", objects);
|
||||
std::printf(" items : %d\n", items);
|
||||
return 0;
|
||||
} else if (std::strcmp(argv[i], "--gen-zone-texture-pack") == 0 && i + 1 < argc) {
|
||||
// Drop a starter PNG texture pack into <zoneDir>/textures/
|
||||
// by fanning out to the procedural --gen-texture-* commands.
|
||||
// Saves the user from sourcing proprietary art when bringing
|
||||
// up a new zone — six themed textures (grass, dirt, stone,
|
||||
// brick, wood, water) cover most outdoor & dungeon needs.
|
||||
std::string zoneDir = argv[++i];
|
||||
uint32_t seed = 1;
|
||||
for (int k = i + 1; k < argc; ++k) {
|
||||
std::string flag = argv[k];
|
||||
if (flag == "--seed" && k + 1 < argc) {
|
||||
try { seed = static_cast<uint32_t>(std::stoul(argv[++k])); } catch (...) {}
|
||||
i = k;
|
||||
} else if (flag.rfind("--", 0) == 0) {
|
||||
std::fprintf(stderr,
|
||||
"gen-zone-texture-pack: unknown flag '%s'\n", flag.c_str());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
std::filesystem::path zp(zoneDir);
|
||||
if (!std::filesystem::exists(zp / "zone.json")) {
|
||||
std::fprintf(stderr,
|
||||
"gen-zone-texture-pack: %s has no zone.json\n",
|
||||
zoneDir.c_str());
|
||||
return 1;
|
||||
}
|
||||
std::filesystem::path texDir = zp / "textures";
|
||||
std::error_code ec;
|
||||
std::filesystem::create_directories(texDir, ec);
|
||||
if (ec) {
|
||||
std::fprintf(stderr,
|
||||
"gen-zone-texture-pack: cannot create %s: %s\n",
|
||||
texDir.string().c_str(), ec.message().c_str());
|
||||
return 1;
|
||||
}
|
||||
std::string self = (argc > 0) ? argv[0] : "wowee_editor";
|
||||
// Each row: {flag, fileName, args...}. Using std::string so
|
||||
// we can interpolate the per-pack seed without sprintf
|
||||
// gymnastics; subprocess invocation handles quoting.
|
||||
struct Cmd {
|
||||
std::string flag;
|
||||
std::string outName;
|
||||
std::vector<std::string> args;
|
||||
};
|
||||
std::vector<Cmd> jobs = {
|
||||
{"--gen-texture-noise", "grass.png", {"4A7C2E", "5C9B3A", "256", "256"}},
|
||||
{"--gen-texture-noise", "dirt.png", {"6B4A2A", "8B5E3A", "256", "256"}},
|
||||
{"--gen-texture-checker", "stone.png", {"7A7A7A", "5A5A5A", "32", "256", "256"}},
|
||||
{"--gen-texture-brick", "brick.png", {"8B4513", "D3D3D3", "64", "24", "4", "256", "256"}},
|
||||
{"--gen-texture-wood", "wood.png", {"8B5A2B", "4A3216", "12", std::to_string(seed), "256", "256"}},
|
||||
{"--gen-texture-radial", "water.png", {"3A6FA0", "1E4A78", "256", "256"}},
|
||||
};
|
||||
int written = 0;
|
||||
for (const auto& job : jobs) {
|
||||
std::filesystem::path out = texDir / job.outName;
|
||||
std::string cmd = "\"" + self + "\" " + job.flag + " \"" + out.string() + "\"";
|
||||
for (const auto& a : job.args) cmd += " " + a;
|
||||
cmd += " > /dev/null 2>&1";
|
||||
int rc = std::system(cmd.c_str());
|
||||
if (rc != 0) {
|
||||
std::fprintf(stderr,
|
||||
"gen-zone-texture-pack: %s failed (rc=%d)\n",
|
||||
job.flag.c_str(), rc);
|
||||
} else {
|
||||
++written;
|
||||
}
|
||||
}
|
||||
std::printf("gen-zone-texture-pack: wrote %d of %zu textures to %s\n",
|
||||
written, jobs.size(), texDir.string().c_str());
|
||||
return written == static_cast<int>(jobs.size()) ? 0 : 1;
|
||||
} else if (std::strcmp(argv[i], "--gen-zone-mesh-pack") == 0 && i + 1 < argc) {
|
||||
// Companion to --gen-zone-texture-pack: drops a starter
|
||||
// WOM mesh pack into <zoneDir>/meshes/. Bootstraps the
|
||||
// mesh side of the open-format pipeline so a fresh zone
|
||||
// has placeholders for outdoor decoration without any
|
||||
// proprietary M2 imports. Each rock variant uses a
|
||||
// different seed so they read as distinct boulders.
|
||||
std::string zoneDir = argv[++i];
|
||||
uint32_t seed = 1;
|
||||
for (int k = i + 1; k < argc; ++k) {
|
||||
std::string flag = argv[k];
|
||||
if (flag == "--seed" && k + 1 < argc) {
|
||||
try { seed = static_cast<uint32_t>(std::stoul(argv[++k])); } catch (...) {}
|
||||
i = k;
|
||||
} else if (flag.rfind("--", 0) == 0) {
|
||||
std::fprintf(stderr,
|
||||
"gen-zone-mesh-pack: unknown flag '%s'\n", flag.c_str());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
std::filesystem::path zp(zoneDir);
|
||||
if (!std::filesystem::exists(zp / "zone.json")) {
|
||||
std::fprintf(stderr,
|
||||
"gen-zone-mesh-pack: %s has no zone.json\n",
|
||||
zoneDir.c_str());
|
||||
return 1;
|
||||
}
|
||||
std::filesystem::path meshDir = zp / "meshes";
|
||||
std::error_code ec;
|
||||
std::filesystem::create_directories(meshDir, ec);
|
||||
if (ec) {
|
||||
std::fprintf(stderr,
|
||||
"gen-zone-mesh-pack: cannot create %s: %s\n",
|
||||
meshDir.string().c_str(), ec.message().c_str());
|
||||
return 1;
|
||||
}
|
||||
std::string self = (argc > 0) ? argv[0] : "wowee_editor";
|
||||
struct MeshJob {
|
||||
std::string flag;
|
||||
std::string outBase; // no .wom extension
|
||||
std::vector<std::string> args;
|
||||
};
|
||||
std::string s0 = std::to_string(seed);
|
||||
std::string s1 = std::to_string(seed + 17);
|
||||
std::string s2 = std::to_string(seed + 41);
|
||||
std::vector<MeshJob> jobs = {
|
||||
// 3 rock variants with distinct seeds for variety
|
||||
{"--gen-mesh-rock", "rock_small", {"0.6", "0.30", "2", s0}},
|
||||
{"--gen-mesh-rock", "rock_medium", {"1.2", "0.25", "2", s1}},
|
||||
{"--gen-mesh-rock", "rock_large", {"2.4", "0.35", "3", s2}},
|
||||
// Tree placeholder, fence segment for boundaries
|
||||
{"--gen-mesh-tree", "tree", {"0.15", "3.0", "1.0"}},
|
||||
{"--gen-mesh-fence", "fence", {"5", "1.2", "1.4", "0.06"}},
|
||||
};
|
||||
int written = 0;
|
||||
for (const auto& job : jobs) {
|
||||
std::filesystem::path out = meshDir / job.outBase;
|
||||
std::string cmd = "\"" + self + "\" " + job.flag + " \"" + out.string() + "\"";
|
||||
for (const auto& a : job.args) cmd += " " + a;
|
||||
cmd += " > /dev/null 2>&1";
|
||||
int rc = std::system(cmd.c_str());
|
||||
if (rc != 0) {
|
||||
std::fprintf(stderr,
|
||||
"gen-zone-mesh-pack: %s failed (rc=%d)\n",
|
||||
job.flag.c_str(), rc);
|
||||
} else {
|
||||
++written;
|
||||
}
|
||||
}
|
||||
std::printf("gen-zone-mesh-pack: wrote %d of %zu meshes to %s\n",
|
||||
written, jobs.size(), meshDir.string().c_str());
|
||||
return written == static_cast<int>(jobs.size()) ? 0 : 1;
|
||||
} else if (std::strcmp(argv[i], "--gen-zone-starter-pack") == 0 && i + 1 < argc) {
|
||||
// Convenience entry point: run --gen-zone-texture-pack
|
||||
// and --gen-zone-mesh-pack in sequence so a fresh zone
|
||||
// gets a full open-format asset bootstrap from a single
|
||||
// command. The seed propagates to both children so a
|
||||
// user can reliably reproduce the same starter pack.
|
||||
std::string zoneDir = argv[++i];
|
||||
uint32_t seed = 1;
|
||||
for (int k = i + 1; k < argc; ++k) {
|
||||
std::string flag = argv[k];
|
||||
if (flag == "--seed" && k + 1 < argc) {
|
||||
try { seed = static_cast<uint32_t>(std::stoul(argv[++k])); } catch (...) {}
|
||||
i = k;
|
||||
} else if (flag.rfind("--", 0) == 0) {
|
||||
std::fprintf(stderr,
|
||||
"gen-zone-starter-pack: unknown flag '%s'\n", flag.c_str());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (!std::filesystem::exists(std::filesystem::path(zoneDir) / "zone.json")) {
|
||||
std::fprintf(stderr,
|
||||
"gen-zone-starter-pack: %s has no zone.json\n",
|
||||
zoneDir.c_str());
|
||||
return 1;
|
||||
}
|
||||
std::string self = (argc > 0) ? argv[0] : "wowee_editor";
|
||||
std::string seedStr = std::to_string(seed);
|
||||
std::printf("gen-zone-starter-pack: %s (seed %u)\n",
|
||||
zoneDir.c_str(), seed);
|
||||
std::printf(" step 1/2: textures\n");
|
||||
std::string cmd1 = "\"" + self + "\" --gen-zone-texture-pack \"" +
|
||||
zoneDir + "\" --seed " + seedStr;
|
||||
int rc1 = std::system(cmd1.c_str());
|
||||
if (rc1 != 0) {
|
||||
std::fprintf(stderr,
|
||||
"gen-zone-starter-pack: texture step failed (rc=%d)\n", rc1);
|
||||
return 1;
|
||||
}
|
||||
std::printf(" step 2/2: meshes\n");
|
||||
std::string cmd2 = "\"" + self + "\" --gen-zone-mesh-pack \"" +
|
||||
zoneDir + "\" --seed " + seedStr;
|
||||
int rc2 = std::system(cmd2.c_str());
|
||||
if (rc2 != 0) {
|
||||
std::fprintf(stderr,
|
||||
"gen-zone-starter-pack: mesh step failed (rc=%d)\n", rc2);
|
||||
return 1;
|
||||
}
|
||||
std::printf("\ngen-zone-starter-pack: complete\n");
|
||||
std::printf(" zone dir : %s\n", zoneDir.c_str());
|
||||
std::printf(" textures : 6 PNGs in textures/\n");
|
||||
std::printf(" meshes : 5 WOMs in meshes/\n");
|
||||
return 0;
|
||||
} else if (std::strcmp(argv[i], "--gen-project-starter-pack") == 0 && i + 1 < argc) {
|
||||
// Project-wide bootstrap. For every zone in <projectDir>,
|
||||
// run --gen-zone-starter-pack (textures + meshes) and
|
||||
// --gen-zone-audio-pack (audio). Each zone gets a unique
|
||||
// sub-seed offset from the base seed so per-zone content
|
||||
// looks distinct (e.g. rocks differ, wood grain differs).
|
||||
//
|
||||
// Pairs with --validate-project-packs as the inverse —
|
||||
// bootstrap, then audit, then ship.
|
||||
std::string projectDir = argv[++i];
|
||||
uint32_t seed = 1;
|
||||
for (int k = i + 1; k < argc; ++k) {
|
||||
std::string flag = argv[k];
|
||||
if (flag == "--seed" && k + 1 < argc) {
|
||||
try { seed = static_cast<uint32_t>(std::stoul(argv[++k])); } catch (...) {}
|
||||
i = k;
|
||||
} else if (flag.rfind("--", 0) == 0) {
|
||||
std::fprintf(stderr,
|
||||
"gen-project-starter-pack: unknown flag '%s'\n", flag.c_str());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
namespace fs = std::filesystem;
|
||||
if (!fs::exists(projectDir) || !fs::is_directory(projectDir)) {
|
||||
std::fprintf(stderr,
|
||||
"gen-project-starter-pack: %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());
|
||||
if (zones.empty()) {
|
||||
std::fprintf(stderr,
|
||||
"gen-project-starter-pack: %s contains no zones\n",
|
||||
projectDir.c_str());
|
||||
return 1;
|
||||
}
|
||||
std::string self = (argc > 0) ? argv[0] : "wowee_editor";
|
||||
std::printf("gen-project-starter-pack: %s (base seed %u)\n",
|
||||
projectDir.c_str(), seed);
|
||||
std::printf(" zones: %zu\n\n", zones.size());
|
||||
int passed = 0, failed = 0;
|
||||
for (size_t z = 0; z < zones.size(); ++z) {
|
||||
std::string zoneSeed = std::to_string(seed + z * 17);
|
||||
std::string name = fs::path(zones[z]).filename().string();
|
||||
std::printf(" [%zu/%zu] %s (seed %s)\n",
|
||||
z + 1, zones.size(), name.c_str(), zoneSeed.c_str());
|
||||
std::string c1 = "\"" + self + "\" --gen-zone-starter-pack \"" +
|
||||
zones[z] + "\" --seed " + zoneSeed +
|
||||
" > /dev/null 2>&1";
|
||||
int rc1 = std::system(c1.c_str());
|
||||
std::string c2 = "\"" + self + "\" --gen-zone-audio-pack \"" +
|
||||
zones[z] + "\" > /dev/null 2>&1";
|
||||
int rc2 = std::system(c2.c_str());
|
||||
if (rc1 == 0 && rc2 == 0) {
|
||||
++passed;
|
||||
std::printf(" OK textures + meshes + audio\n");
|
||||
} else {
|
||||
++failed;
|
||||
std::printf(" FAIL starter rc=%d, audio rc=%d\n", rc1, rc2);
|
||||
}
|
||||
}
|
||||
std::printf("\n Total: %d passed, %d failed\n", passed, failed);
|
||||
return failed == 0 ? 0 : 1;
|
||||
} else if (std::strcmp(argv[i], "--info-zone-summary") == 0 && i + 1 < argc) {
|
||||
// One-glance health digest for a zone. Combines the per-
|
||||
// category counts/bytes from the inventory commands with
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue