diff --git a/tools/editor/editor_app.cpp b/tools/editor/editor_app.cpp index efbba655..fc6802ee 100644 --- a/tools/editor/editor_app.cpp +++ b/tools/editor/editor_app.cpp @@ -101,6 +101,7 @@ void EditorApp::run() { if (autoSaveTimer_ >= autoSaveInterval_) { autoSaveTimer_ = 0.0f; quickSave(); + showToast("Auto-saved", 2.0f); LOG_INFO("Auto-saved zone"); } } @@ -969,10 +970,28 @@ void EditorApp::exportZone(const std::string& outputDir) { } // Write zone manifest (for client loading) + // Scan output directory for all exported tiles (includes adjacent tiles) ZoneManifest manifest; manifest.mapName = loadedMap_; manifest.displayName = loadedMap_; manifest.tiles.push_back({loadedTileX_, loadedTileY_}); + namespace fs = std::filesystem; + if (fs::exists(base)) { + for (auto& entry : fs::directory_iterator(base)) { + if (entry.path().extension() != ".adt") continue; + std::string stem = entry.path().stem().string(); + auto lastU = stem.rfind('_'); + auto prevU = stem.rfind('_', lastU - 1); + if (lastU != std::string::npos && prevU != std::string::npos) { + try { + int tx = std::stoi(stem.substr(prevU + 1, lastU - prevU - 1)); + int ty = std::stoi(stem.substr(lastU + 1)); + if (tx == loadedTileX_ && ty == loadedTileY_) continue; + manifest.tiles.push_back({tx, ty}); + } catch (...) {} + } + } + } manifest.hasCreatures = (npcSpawner_.spawnCount() > 0); manifest.baseHeight = terrain_.chunks[0].position[2]; manifest.save(base + "/zone.json"); diff --git a/tools/editor/editor_app.hpp b/tools/editor/editor_app.hpp index 85ec9d65..97b38e72 100644 --- a/tools/editor/editor_app.hpp +++ b/tools/editor/editor_app.hpp @@ -149,6 +149,11 @@ public: void showToast(const std::string& msg, float duration = 3.0f); const std::vector& getToasts() const { return toasts_; } const std::vector& getRecentZones() const { return recentZones_; } + bool isAutoSaveEnabled() const { return autoSaveEnabled_; } + void setAutoSaveEnabled(bool v) { autoSaveEnabled_ = v; } + float getAutoSaveInterval() const { return autoSaveInterval_; } + void setAutoSaveInterval(float s) { autoSaveInterval_ = std::clamp(s, 60.0f, 900.0f); } + float getAutoSaveTimeRemaining() const { return autoSaveInterval_ - autoSaveTimer_; } void updateToasts(float dt); private: size_t lastObjCount_ = 0; diff --git a/tools/editor/editor_ui.cpp b/tools/editor/editor_ui.cpp index 49f72ec9..d85ff7d0 100644 --- a/tools/editor/editor_ui.cpp +++ b/tools/editor/editor_ui.cpp @@ -375,6 +375,17 @@ void EditorUI::renderMenuBar(EditorApp& app) { auto& te = app.getTerrainEditor(); if (ImGui::MenuItem("Undo", "Ctrl+Z", false, te.history().canUndo())) te.undo(); if (ImGui::MenuItem("Redo", "Ctrl+Shift+Z", false, te.history().canRedo())) te.redo(); + ImGui::Separator(); + if (ImGui::BeginMenu("Auto-Save Settings")) { + bool enabled = app.isAutoSaveEnabled(); + if (ImGui::Checkbox("Enabled", &enabled)) app.setAutoSaveEnabled(enabled); + float interval = app.getAutoSaveInterval(); + if (ImGui::SliderFloat("Interval (sec)", &interval, 60.0f, 900.0f, "%.0fs")) + app.setAutoSaveInterval(interval); + ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1), + "Next in: %.0fs", app.getAutoSaveTimeRemaining()); + ImGui::EndMenu(); + } ImGui::EndMenu(); } if (ImGui::BeginMenu("View")) {