fix(editor): version string, NPC ID reset, author attribution + UX

Bug fixes:
- Fix README.txt version from v0.8.0 to v1.0.0
- Reset NPC idCounter_ on loadFromFile to prevent ID collisions
- WCP content pack uses project author/description if loaded instead
  of hardcoded "Kelsi Davis"

New features:
- Select by Type: context menu items for "Select All M2 Models" and
  "Select All WMO Buildings" for batch type-based selection
- selectByType(PlaceableType) added to ObjectPlacer
- Export summary toast now shows object/NPC/quest counts alongside
  file count and open format score (5s duration)
This commit is contained in:
Kelsi 2026-05-05 14:05:22 -07:00
parent 28d63addc4
commit 10a63f0581
5 changed files with 31 additions and 5 deletions

View file

@ -961,7 +961,7 @@ void EditorApp::exportZone(const std::string& outputDir) {
readme << "Objects: " << objectPlacer_.objectCount() << "\n";
readme << "NPCs: " << npcSpawner_.spawnCount() << "\n";
readme << "Quests: " << questEditor_.questCount() << "\n";
readme << "Created with Wowee World Editor v0.8.0\n\n";
readme << "Created with Wowee World Editor v1.0.0\n\n";
readme << "\nOpen Formats (no Blizzard IP):\n";
readme << " .wot/.whm — Wowee Open Terrain (heightmap + metadata)\n";
readme << " .wom — Wowee Open Model (static 3D models)\n";
@ -1037,8 +1037,12 @@ void EditorApp::exportZone(const std::string& outputDir) {
if (stats) stats << sj.dump(2) << "\n";
}
showToast("Exported " + std::to_string(fileCount) + " files (" +
std::to_string(score) + "/6 open format)");
std::string summary = std::to_string(fileCount) + " files exported";
if (objectPlacer_.objectCount() > 0) summary += ", " + std::to_string(objectPlacer_.objectCount()) + " obj";
if (npcSpawner_.spawnCount() > 0) summary += ", " + std::to_string(npcSpawner_.spawnCount()) + " NPC";
if (questEditor_.questCount() > 0) summary += ", " + std::to_string(questEditor_.questCount()) + " quest";
summary += " (score " + std::to_string(score) + "/6)";
showToast(summary, 5.0f);
LOG_INFO("=== Zone Export Summary ===");
LOG_INFO(" Output: ", base);
LOG_INFO(" Open format score: ", score, "/6");
@ -1059,8 +1063,9 @@ void EditorApp::exportContentPack(const std::string& destPath) {
// Pack into WCP
ContentPackInfo info;
info.name = loadedMap_;
info.author = "Kelsi Davis";
info.description = "Custom zone created with Wowee World Editor";
info.author = project_.author.empty() ? "Kelsi Davis" : project_.author;
info.description = project_.description.empty()
? "Custom zone created with Wowee World Editor" : project_.description;
info.mapId = 9000;
if (ContentPacker::packZone(dir, loadedMap_, destPath, info))
showToast("Content pack exported: " + destPath);

View file

@ -2076,6 +2076,14 @@ void EditorUI::renderContextMenu(EditorApp& app) {
if (ImGui::MenuItem("Select All", "Ctrl+A")) {
app.getObjectPlacer().selectAll();
}
if (ImGui::MenuItem("Select All M2 Models")) {
app.getObjectPlacer().selectByType(PlaceableType::M2);
app.showToast("Selected " + std::to_string(app.getObjectPlacer().selectionCount()) + " M2 models");
}
if (ImGui::MenuItem("Select All WMO Buildings")) {
app.getObjectPlacer().selectByType(PlaceableType::WMO);
app.showToast("Selected " + std::to_string(app.getObjectPlacer().selectionCount()) + " WMO buildings");
}
if (ImGui::MenuItem("Deselect")) {
app.getObjectPlacer().clearSelection();
app.getNpcSpawner().clearSelection();

View file

@ -129,6 +129,7 @@ bool NpcSpawner::loadFromFile(const std::string& path) {
spawns_.clear();
selectedIdx_ = -1;
idCounter_ = 1;
for (const auto& js : arr) {
CreatureSpawn s;

View file

@ -120,6 +120,17 @@ void ObjectPlacer::selectAll() {
if (!objects_.empty()) selectedIdx_ = 0;
}
void ObjectPlacer::selectByType(PlaceableType type) {
clearSelection();
for (int i = 0; i < static_cast<int>(objects_.size()); i++) {
if (objects_[i].type == type) {
objects_[i].selected = true;
selectedIndices_.push_back(i);
}
}
if (!selectedIndices_.empty()) selectedIdx_ = selectedIndices_[0];
}
void ObjectPlacer::moveSelected(const glm::vec3& delta) {
if (selectedIndices_.size() > 1) {
for (int idx : selectedIndices_) objects_[idx].position += delta;

View file

@ -61,6 +61,7 @@ public:
const std::vector<PlacedObject>& getObjects() const { return objects_; }
std::vector<PlacedObject>& getObjects() { return objects_; }
void selectAll();
void selectByType(PlaceableType type);
void clearAll() { objects_.clear(); undoStack_.clear(); selectedIdx_ = -1; selectedIndices_.clear(); }
size_t objectCount() const { return objects_.size(); }