From e516c3c71f5e6dc70244113735838693d4c1a8ae Mon Sep 17 00:00:00 2001 From: Kelsi Date: Tue, 5 May 2026 07:21:59 -0700 Subject: [PATCH] feat(editor): one-click Generate Complete Zone pipeline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - File > Generate Complete Zone: runs the full procedural pipeline in one click: noise → smooth (3 passes) → recalc normals → height-based auto-paint (sand/grass/rock/snow) → slope-based cliff paint (rock on steep faces) - Creates a fully textured, natural-looking zone from flat terrain - Removed stale quickGenerate checkbox from New Terrain dialog --- tools/editor/editor_app.cpp | 35 +++++++++++++++++++++++++++++++++++ tools/editor/editor_app.hpp | 1 + tools/editor/editor_ui.cpp | 8 +++----- 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/tools/editor/editor_app.cpp b/tools/editor/editor_app.cpp index 4b2c2151..b2178a17 100644 --- a/tools/editor/editor_app.cpp +++ b/tools/editor/editor_app.cpp @@ -816,6 +816,41 @@ void EditorApp::flyToSelected() { } } +void EditorApp::generateCompleteZone() { + if (!terrain_.isLoaded()) return; + showToast("Generating zone..."); + + // Step 1: Apply noise + terrainEditor_.applyNoise(0.005f, 30.0f, 4, 42); + + // Step 2: Smooth + terrainEditor_.smoothEntireTile(3); + + // Step 3: Recalc normals for slope paint + std::vector allChunks; + for (int i = 0; i < 256; i++) allChunks.push_back(i); + terrainEditor_.recalcNormals(allChunks); + + // Step 4: Auto-paint by height + std::vector bands = { + {90.0f, "Tileset\\Tanaris\\TanarisSandBase01.blp"}, + {110.0f, "Tileset\\Elwynn\\ElwynnGrassBase.blp"}, + {140.0f, "Tileset\\Barrens\\BarrensRock01.blp"}, + {99999.0f, "Tileset\\Expansion02\\Dragonblight\\DragonblightFreshSmoothSnowA.blp"} + }; + texturePainter_.autoPaintByHeight(bands); + + // Step 5: Slope paint (rock on cliffs) + texturePainter_.autoPaintBySlope(0.4f, "Tileset\\Desolace\\DesolaceRock01.blp"); + + // Refresh + auto mesh = terrainEditor_.regenerateMesh(); + viewport_.clearTerrain(); + viewport_.loadTerrain(mesh, terrain_.textures, loadedTileX_, loadedTileY_); + + showToast("Zone generated!"); +} + void EditorApp::clearAllObjects() { vkDeviceWaitIdle(window_->getVkContext()->getDevice()); objectPlacer_.clearAll(); diff --git a/tools/editor/editor_app.hpp b/tools/editor/editor_app.hpp index 64de4a27..c2d31a01 100644 --- a/tools/editor/editor_app.hpp +++ b/tools/editor/editor_app.hpp @@ -77,6 +77,7 @@ public: void snapSelectedToGround(); void flyToSelected(); void clearAllObjects(); + void generateCompleteZone(); void centerOnTerrain(); // Multi-tile support diff --git a/tools/editor/editor_ui.cpp b/tools/editor/editor_ui.cpp index aa9862fd..23d0f0a6 100644 --- a/tools/editor/editor_ui.cpp +++ b/tools/editor/editor_ui.cpp @@ -141,9 +141,10 @@ void EditorUI::renderMenuBar(EditorApp& app) { } ImGui::EndMenu(); } - if (ImGui::MenuItem("Clear All Objects/NPCs", nullptr, false, app.hasTerrainLoaded())) { + if (ImGui::MenuItem("Generate Complete Zone", nullptr, false, app.hasTerrainLoaded())) + app.generateCompleteZone(); + if (ImGui::MenuItem("Clear All Objects/NPCs", nullptr, false, app.hasTerrainLoaded())) app.clearAllObjects(); - } ImGui::Separator(); if (ImGui::MenuItem("Quick Save", "Ctrl+S", false, app.hasTerrainLoaded())) app.quickSave(); @@ -345,9 +346,6 @@ void EditorUI::renderNewTerrainDialog(EditorApp& /*app*/) { ImGui::TextColored(ImVec4(0.5f, 0.6f, 0.5f, 1.0f), " + %s", bt.detail); ImGui::Spacing(); - static bool quickGenerate = false; - ImGui::Checkbox("Quick Generate (noise + smooth + auto-paint)", &quickGenerate); - if (ImGui::Button("Create", ImVec2(120, 0))) { newRequested_ = true; showNewDialog_ = false; } ImGui::SameLine(); if (ImGui::Button("Cancel", ImVec2(120, 0))) showNewDialog_ = false;