diff --git a/src/render/Viewer.cpp b/src/render/Viewer.cpp index 929c660..ebd7728 100644 --- a/src/render/Viewer.cpp +++ b/src/render/Viewer.cpp @@ -305,7 +305,9 @@ void Viewer::stepSim() { if (liveWorld) { // --- Live World: advance the slow clock; geology is frozen -------- double dtH = (!paused) ? liveRate * GetFrameTime() : 0.0; // simulated hours this frame - liveAdvance(dtH, dtH); // liveAdvance records step-back snapshots itself + if (dtH > 0.0 && (wxUndo.empty() || liveTime - wxUndo.back().t >= liveRate - 1e-9)) + wxPushSnapshot(); // throttled history during a continuous run (~1 snapshot/sec) + liveAdvance(dtH, dtH); return; } if (!paused && !settled) { @@ -344,17 +346,6 @@ void Viewer::stepSim() { // integrated, non-reversible path, so it advances by dtWeather (0 = hold, used for a backward // step which still rewinds the deterministic sky: day/night, tides, seasons, moon phases). void Viewer::liveAdvance(double dtClock, double dtWeather) { - // Record a step-back snapshot of the PRE-advance state at ~one-step cadence, on ANY forward - // advance (continuous run or manual step) -- so stepping back reverses weather + storms whether - // they were born while stepping or during a continuous run. interval ~ liveRate means roughly - // one snapshot per real second regardless of the clock rate (bounded ring, drops oldest). - if (dtClock > 0.0) { - double interval = std::max(1e-6, liveRate); - if (wxUndo.empty() || liveTime - wxUndo.back().t >= interval - 1e-9) { - if ((int)wxUndo.size() >= wxUndoMax) wxUndo.erase(wxUndo.begin()); - wxUndo.push_back(WxFrame{ liveTime, planet.captureWeather() }); - } - } liveTime = std::max(0.0, liveTime + dtClock); double days = liveTime / planet.cfg.dayLengthHours; double dayOfYear01 = days / planet.cfg.yearLengthDays; dayOfYear01 -= std::floor(dayOfYear01); @@ -375,10 +366,17 @@ void Viewer::liveAdvance(double dtClock, double dtWeather) { rebuildLiveOverlay(); } -// Step the live clock forward one rate-unit. Auto-pauses (like a video frame-step); liveAdvance -// records the pre-step snapshot so the backward step can restore weather + storms exactly. +// Push the current (pre-advance) weather state onto the bounded step-back ring. +void Viewer::wxPushSnapshot() { + if ((int)wxUndo.size() >= wxUndoMax) wxUndo.erase(wxUndo.begin()); + wxUndo.push_back(WxFrame{ liveTime, planet.captureWeather() }); +} + +// Step the live clock forward one rate-unit. Auto-pauses (like a video frame-step); always records +// the pre-step snapshot first (rate-independent) so the backward step restores weather + storms. void Viewer::liveStepForward() { paused = true; + wxPushSnapshot(); liveAdvance(liveRate, liveRate); } @@ -393,8 +391,10 @@ void Viewer::liveStepBack() { liveTime = f.t; planet.restoreWeather(f.w); liveAdvance(0.0, 0.0); // recompute the sky/overlay at the restored time (weather held) + setStatus("Step back"); } else { - liveAdvance(-liveRate, 0.0); // no history: deterministic sky rewinds, weather holds + liveAdvance(-liveRate, 0.0); // no recorded past (e.g. right after a load): sky rewinds, weather holds + setStatus("Step back (sky only - no earlier weather; play/step forward first)"); } } diff --git a/src/render/Viewer.hpp b/src/render/Viewer.hpp index 8e49f4b..9d40628 100644 --- a/src/render/Viewer.hpp +++ b/src/render/Viewer.hpp @@ -145,6 +145,7 @@ struct Viewer { void liveAdvance(double dtClock, double dtWeather); // advance the Live World clock + fields void liveStepForward(); // step the clock forward one rate-unit (snapshots for undo) void liveStepBack(); // step everything back one frame (restores weather/storms) + void wxPushSnapshot(); // push the current weather state onto the step-back ring Rectangle mapViewRect() const; // 2D map projection rect after zoom/pan (scissor stays mapRect) // ---- Input (ViewerInput.cpp) -------------------------------------------- diff --git a/src/render/ViewerInput.cpp b/src/render/ViewerInput.cpp index 3e34032..3158540 100644 --- a/src/render/ViewerInput.cpp +++ b/src/render/ViewerInput.cpp @@ -211,7 +211,7 @@ void Viewer::handleInput() { // backward restores the snapshot from the last forward step -> everything (incl. weather + // storms) steps back, within the current paused stepping session. if (IsKeyPressed(KEY_PERIOD) && liveWorld) { liveStepForward(); setStatus("Step forward"); } - if (IsKeyPressed(KEY_COMMA) && liveWorld) { liveStepBack(); setStatus(wxUndo.empty() ? "Step back (sky only)" : "Step back"); } + if (IsKeyPressed(KEY_COMMA) && liveWorld) { liveStepBack(); } // liveStepBack sets its own status if (IsKeyPressed(KEY_F)) { // fast-forward to settled if (!settled) { while (!settled) stepOnce();