From 336c940c28e77b6afe4ed098d295a67ca26e9be8 Mon Sep 17 00:00:00 2001 From: maj00r Date: Sat, 24 Oct 2026 18:20:22 +0200 Subject: [PATCH] fix(editor): laying leaves the terrain as it is: the track takes from the ground only the heights of the points clicked, from point to point by default, and no formation is led into the terrain after it, nor after a track dragged from a free end; the terrain made from the model never makes a chunk there is anew, made from the model or by hand, edited or not, only the missing ones, the formations laid anew as the tracks lie The terrain under the tracks and the end of Tracks onto the terrain took every chunk along the tracks away and made it again from the model, the changes made by hand with them (79 chunks on test2). The heights while laying are kept under a key of their own, so the fitted ones chosen when they were the default are left behind; fitted stays a choice. --- application/editormode.h | 6 ++++-- application/editormodelay.cpp | 8 +++++++- application/editormodenmt.cpp | 25 ++++++++----------------- editor/editorSettings.cpp | 6 ++++-- editor/editorSettings.hpp | 2 +- lang/editor_pl.po | 4 ++-- 6 files changed, 26 insertions(+), 25 deletions(-) diff --git a/application/editormode.h b/application/editormode.h index a4f9d060..5b3df340 100644 --- a/application/editormode.h +++ b/application/editormode.h @@ -332,6 +332,7 @@ class editor_mode : public application_mode, private editor_track::observer, pri double band{300.0}; // m from the tracks the chunks made along them reach bool shape{true}; // the formation and the slopes of the tracks as modifiers of the terrain bool grow{true}; // while a track is laid, the terrain is made around the cursor where there's none + bool laying{false}; // the tracks committed are being laid: they leave the terrain as it is bool grown{false}; // the chunks waiting were all asked for by growing: the formations aren't made anew after them double grow_time{-10.0}; double slope{1.5}; @@ -413,8 +414,9 @@ class editor_mode : public application_mode, private editor_track::observer, pri double nmt_offset_at(double const X, double const Z) const; std::vector nmt_keys_around() const; std::vector nmt_keys_along_tracks() const; - // Rebuild: the chunks there already are made anew too, and the formation laid before is forgotten, as when the tracks moved - void nmt_make(std::vector const &Keys, bool const Rebuild = false); + // only the chunks there are none of yet: a chunk there is, made from the model or by hand, edited or not, is never made anew. + // Reshape: the formations of the tracks laid anew as the tracks lie now, as when they moved + void nmt_make(std::vector const &Keys, bool const Reshape = false); enum class nmt_chunk { waiting, // for its squares of the model diff --git a/application/editormodelay.cpp b/application/editormodelay.cpp index 53e3a7fa..6ba7c998 100644 --- a/application/editormodelay.cpp +++ b/application/editormodelay.cpp @@ -638,6 +638,8 @@ void editor_mode::finish_extend() m_extend.active = false; if (pieces.empty() || style == nullptr) return; + // the track laid takes only its heights from the ground: the terrain is shaped under it by the buttons of the terrain model + m_nmt_state.laying = true; std::vector created; for (auto const &piece : pieces) created.push_back(editor_track::create_path(*style, piece)); @@ -652,6 +654,7 @@ void editor_mode::finish_extend() m_node = created.back(); ui()->set_node(m_node); nmt_fit_laid(from, created.back()->m_paths.front().points[segment_data::point::end]); + m_nmt_state.laying = false; straight_refresh(); } @@ -1128,6 +1131,8 @@ void editor_mode::lay_finish(editor_track::snap_target const &End) auto const *style{tool.start.track != nullptr ? tool.start.track : End.track}; if (style == nullptr && tool.copy_selected) style = selected_track(); + // the track laid takes only its heights from the ground: the terrain is shaped under it by the buttons of the terrain model + m_nmt_state.laying = true; std::vector created; for (auto const &piece : pieces) created.push_back(style != nullptr ? editor_track::create_path(*style, piece) : editor_track::create_path(tool.style, piece)); @@ -1170,6 +1175,7 @@ void editor_mode::lay_finish(editor_track::snap_target const &End) ui()->set_node(m_node); if (nmt_fit_laid(tool.history, created.back()->m_paths.front().points[segment_data::point::end])) tool.status += "\n" + STR("The grade line of the whole track laid in a row fitted to the terrain model, as the tracks go onto the terrain"); + m_nmt_state.laying = false; WriteLog("Editor: " + tool.status, logtype::generic); tool.points.clear(); tool.start = {}; @@ -1541,7 +1547,7 @@ void editor_mode::render_lay_ui() ImGui::TextDisabled("%s", STR_C("Height of the track on the ground")); if (int heights{static_cast(EditorSettings.heights())}; segmented("layheights", heights, - {{0, STR_C("Fitted"), "The grades fitted to the ground as Tracks onto the terrain fits them: vertical curves of the norms, the bumps of the ground gone past, the earthworks made by the terrain. On the terrain model the whole track laid in a row is fitted again at each click"}, + {{0, STR_C("Fitted"), "The grades fitted to the ground as Tracks onto the terrain fits them: vertical curves of the norms, the bumps of the ground gone past; the terrain is left as it is. On the terrain model the whole track laid in a row is fitted again at each click"}, {1, STR_C("Point to point"), "Each point clicked at the height of the ground, an even grade between them: the grade changes only where you click"}, {2, STR_C("Flat"), "The track goes on at the height it's laid from, whatever the ground; the first point on the ground"}})) { diff --git a/application/editormodenmt.cpp b/application/editormodenmt.cpp index 9630cb94..ebf76778 100644 --- a/application/editormodenmt.cpp +++ b/application/editormodenmt.cpp @@ -534,7 +534,7 @@ std::vector editor_mode::nmt_keys_along_tracks() const return {keys.begin(), keys.end()}; } -void editor_mode::nmt_make(std::vector const &Keys, bool const Rebuild) +void editor_mode::nmt_make(std::vector const &Keys, bool const Reshape) { auto &state{m_nmt_state}; if (false == ensure_terrain()) @@ -543,21 +543,6 @@ void editor_mode::nmt_make(std::vector const &Keys, bool c return; } nmt_locate(); - if (Rebuild) - { - // the terrain made for the tracks before, as they lay then: the formation of the earlier runs, and the chunks along them, - // whose heights went with it - auto const dropped{m_streamer.drop_modifiers("nmt ")}; - std::size_t removed{0}; - for (auto const &key : Keys) - if (m_streamer.exists(key)) - { - m_streamer.remove_chunk(key.first, key.second); - ++removed; - } - forget_ground(); - WriteLog(format("Editor: NMT - made anew: %zu chunks, %zu formations of the tracks forgotten", removed, dropped), logtype::generic); - } std::size_t queued{0}; for (auto const &key : Keys) if (false == m_streamer.exists(key) && std::find(state.pending.begin(), state.pending.end(), key) == state.pending.end()) @@ -575,6 +560,12 @@ void editor_mode::nmt_make(std::vector const &Keys, bool c if (queued > 0 && false == m_orthophoto.enabled()) m_orthophoto.enabled(true); state.status = queued > 0 ? format(STR_P("%zu chunk to make from the terrain model", "%zu chunks to make from the terrain model", queued), queued) : STR("There's terrain there already"); + // with chunks to make the formations are laid once they're made + if (Reshape && queued == 0 && state.shape) + { + nmt_shape_tracks(); + state.status += format(STR_P("; the formation of %zu path shaped", "; the formation of %zu paths shaped", state.shaped), state.shaped); + } } bool editor_mode::nmt_ready(glm::dvec2 const &Min, glm::dvec2 const &Max) @@ -667,7 +658,7 @@ bool editor_mode::nmt_terrain_along(TTrack const &Track, bool &Waiting) void editor_mode::nmt_track_changed(std::vector const &Tracks) { auto &state{m_nmt_state}; - if (state.restoring || state.stage != nmt_state::automatic::idle || Tracks.empty() || false == m_streamer.active()) + if (state.restoring || state.laying || state.stage != nmt_state::automatic::idle || Tracks.empty() || false == m_streamer.active()) return; for (auto *track : Tracks) if (track != nullptr) diff --git a/editor/editorSettings.cpp b/editor/editorSettings.cpp index 1fc92150..fab20dcb 100644 --- a/editor/editorSettings.cpp +++ b/editor/editorSettings.cpp @@ -116,7 +116,9 @@ bool editorSettings::load() m_top_rails = static_cast(std::strtoul(value.c_str(), nullptr, 16)) | 0xff000000u; else if (key == "track_norms") m_norms = value == "free" ? track_norms::free_laying : value == "plk" ? track_norms::plk : track_norms::ask; - else if (key == "lay_heights") + // under a key of its own since the laying goes from point to point unless told otherwise: the fitted heights chosen + // before, when they were the default, are left behind + else if (key == "laying_heights") m_heights = value == "points" ? lay_heights::points : value == "level" ? lay_heights::level : lay_heights::fitted; else if (key.rfind(origin_prefix, 0) == 0) { @@ -167,7 +169,7 @@ bool editorSettings::save() stream << "top_tracks " << m_top_tracks << "\n"; stream << "top_rails " << std::hex << (m_top_rails & 0xffffffu) << std::dec << "\n"; stream << "track_norms " << (m_norms == track_norms::free_laying ? "free" : m_norms == track_norms::plk ? "plk" : "ask") << "\n"; - stream << "lay_heights " << (m_heights == lay_heights::points ? "points" : m_heights == lay_heights::level ? "level" : "fitted") << "\n"; + stream << "laying_heights " << (m_heights == lay_heights::points ? "points" : m_heights == lay_heights::level ? "level" : "fitted") << "\n"; stream << std::fixed << std::setprecision(3); for (auto const &origin : m_orthophoto_origins) stream << origin.first << " " << origin.second.first << ";" << origin.second.second << "\n"; diff --git a/editor/editorSettings.hpp b/editor/editorSettings.hpp index 45a964b9..b2572ca9 100644 --- a/editor/editorSettings.hpp +++ b/editor/editorSettings.hpp @@ -102,7 +102,7 @@ private: int m_top_tracks{0}; // the railway in the top view: whole, without the ballast, the rails alone std::uint32_t m_top_rails{0xffff6e28}; // colour of the rails alone, as ImGui keeps it: ABGR track_norms m_norms{track_norms::ask}; - lay_heights m_heights{lay_heights::fitted}; + lay_heights m_heights{lay_heights::points}; }; // global editor settings instance diff --git a/lang/editor_pl.po b/lang/editor_pl.po index f1e8205d..fd7068ca 100644 --- a/lang/editor_pl.po +++ b/lang/editor_pl.po @@ -11524,8 +11524,8 @@ msgstr "Punkt–punkt" msgid "Flat" msgstr "Poziomo" -msgid "The grades fitted to the ground as Tracks onto the terrain fits them: vertical curves of the norms, the bumps of the ground gone past, the earthworks made by the terrain. On the terrain model the whole track laid in a row is fitted again at each click" -msgstr "Pochylenia dopasowane do terenu tak jak w „Tory na teren”: łuki pionowe według norm, drobne nierówności terenu pominięte, nasypy i wykopy robi teren. Na modelu terenu (NMT) cały tor kładziony za jednym razem jest dopasowywany od nowa przy każdym kliknięciu" +msgid "The grades fitted to the ground as Tracks onto the terrain fits them: vertical curves of the norms, the bumps of the ground gone past; the terrain is left as it is. On the terrain model the whole track laid in a row is fitted again at each click" +msgstr "Pochylenia dopasowane do terenu tak jak w „Tory na teren”: łuki pionowe według norm, drobne nierówności terenu pominięte; teren zostaje bez zmian. Na modelu terenu (NMT) cały tor kładziony za jednym razem jest dopasowywany od nowa przy każdym kliknięciu" msgid "Each point clicked at the height of the ground, an even grade between them: the grade changes only where you click" msgstr "Każdy kliknięty punkt na wysokości terenu, między punktami równe pochylenie: pochylenie zmienia się tylko tam, gdzie klikniesz"