From d0ff7be1c22a61a3a514e86af0e7f1489e91b3c1 Mon Sep 17 00:00:00 2001 From: maj00r Date: Wed, 21 Oct 2026 17:34:41 +0200 Subject: [PATCH] feat(editor): the fields of the features switched off in the build are shown greyed with the reason instead of hidden The frog, movable nose and 3D sleeper and timber fields of the track properties and the frog chips of the switch panel stay in place while track_features::crossings or track_features::sleepers are off, greyed, with a tooltip saying the feature is switched off in this build; nothing changes them, copying and pasting the properties leaves them out. --- application/editormodetrack.cpp | 7 +++++-- application/editormodetrackprops.cpp | 23 +++++++++++++++-------- lang/editor_pl.po | 3 +++ 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/application/editormodetrack.cpp b/application/editormodetrack.cpp index fa749cda..1da2fb0c 100644 --- a/application/editormodetrack.cpp +++ b/application/editormodetrack.cpp @@ -1081,18 +1081,21 @@ void editor_mode::render_turnout_ui() drive_ui(*track); if (set.has_value()) drive_ui(*set->second); - if (track_features::crossings) { bool frogs{track->SwitchExtension->m_frogs}; bool movable{track->SwitchExtension->m_movablenose}; char const *const frogtip{"Cuts the rails of the switch at its frog and lays wing rails and check rails.\n" "Off for a switch whose include has its own model of them"}; char const *const nosetip{"The nose of the frog moves with the blades over to the wing rail of the track set, leaving no gap; the frog has no check rails"}; + ImGui::BeginDisabled(false == track_features::crossings); if (frogs) toggle_chips("switchfrogs", {{STR_C("Frog and check rails made from the rails"), &frogs, frogtip}, {STR_C("Movable nose"), &movable, nosetip}}); else toggle_chips("switchfrogs", {{STR_C("Frog and check rails made from the rails"), &frogs, frogtip}}); - if (frogs != track->SwitchExtension->m_frogs || movable != track->SwitchExtension->m_movablenose) + ImGui::EndDisabled(); + if (false == track_features::crossings && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) + ImGui::SetTooltip("%s", STR_C("Switched off in this build of the simulator")); + if (track_features::crossings && (frogs != track->SwitchExtension->m_frogs || movable != track->SwitchExtension->m_movablenose)) { auto const before{editor_track::capture(*track)}; track->SwitchExtension->m_frogs = frogs; diff --git a/application/editormodetrackprops.cpp b/application/editormodetrackprops.cpp index 8804e819..1ca44c6d 100644 --- a/application/editormodetrackprops.cpp +++ b/application/editormodetrackprops.cpp @@ -239,6 +239,7 @@ struct track_property char const *empty{nullptr}; // hint of an empty field std::vector choices; std::function applies; + bool off{false}; // the feature isn't in this build: the field is shown greyed and nothing changes it std::function get; // false: the text doesn't fit the track or changes nothing, the track stays as it was std::function set; @@ -434,7 +435,8 @@ std::vector make_properties() { auto &property{add(list, "frogs", field::check, section::look, group::frogs, "Frog and check rails made from the rails", "Cuts the rails of the switch at its frog and lays wing rails and check rails.\nOff for a switch whose include has its own model of them")}; property.rebuild = true; - property.applies = [](TTrack const &Track) { return track_features::crossings && Track.eType == tt_Switch && Track.SwitchExtension != nullptr; }; + property.applies = [](TTrack const &Track) { return Track.eType == tt_Switch && Track.SwitchExtension != nullptr; }; + property.off = false == track_features::crossings; property.get = [](TTrack const &Track) { return std::string{Track.SwitchExtension->m_frogs ? "1" : "0"}; }; property.set = [](TTrack &Track, std::string const &Text) { auto const frogs{Text == "1"}; @@ -447,7 +449,8 @@ std::vector make_properties() { auto &property{add(list, "movablenose", field::check, section::look, group::frogs, "Movable nose", "The nose of the frog moves with the blades over to the wing rail of the track set, leaving no gap; the frog has no check rails")}; property.rebuild = true; - property.applies = [](TTrack const &Track) { return track_features::crossings && Track.eType == tt_Switch && Track.SwitchExtension != nullptr; }; + property.applies = [](TTrack const &Track) { return Track.eType == tt_Switch && Track.SwitchExtension != nullptr; }; + property.off = false == track_features::crossings; property.get = [](TTrack const &Track) { return std::string{Track.SwitchExtension->m_movablenose ? "1" : "0"}; }; property.set = [](TTrack &Track, std::string const &Text) { auto const movable{Text == "1"}; @@ -559,7 +562,7 @@ std::vector make_properties() { auto &property{add(list, "sleeperpack", field::choice, section::look_sleepers, group::sleepers, "Sleeper model from the pack", "Model of the sleepers of the track running alone, of the models of sleepers in the scenery data, laid as 3D sleepers\nin place of the one set with sleepers3dplain in eu07.ini. (as in eu07.ini): the one set there")}; property.rebuild = true; - property.applies = [](TTrack const &Track) { return track_features::sleepers && Track.m_visible; }; + property.off = false == track_features::sleepers; property.choices = choices(sleepermodels); property.get = [index_of](TTrack const &Track) { return std::to_string(Track.m_sleeper_enabled ? index_of(sleepermodels, Track.m_sleeper_model_name) : 0); }; property.set = [](TTrack &Track, std::string const &Text) { @@ -577,7 +580,7 @@ std::vector make_properties() { auto &property{add(list, "timbermodel", field::choice, section::look_sleepers, group::sleepers, "Timber model", "Model of the timbers under the switch or the crossing the track is part of, of the models of timbers in the scenery data,\nin place of the one set with sleepers3d in eu07.ini. It's put together from its submodels begin, main and end to the length of each timber")}; property.rebuild = true; - property.applies = [](TTrack const &Track) { return track_features::sleepers && Track.m_visible; }; + property.off = false == track_features::sleepers; property.choices = choices(timbermodels); property.get = [index_of](TTrack const &Track) { return std::to_string(index_of(timbermodels, Track.m_timber_model_name)); }; property.set = [](TTrack &Track, std::string const &Text) { @@ -594,7 +597,7 @@ std::vector make_properties() { auto &property{add(list, "timberskin", field::text, section::look_sleepers, group::sleepers, "Timber skin", "Replaceable skin of the timber model, empty: the one of the model")}; property.rebuild = true; - property.applies = [](TTrack const &Track) { return track_features::sleepers && Track.m_visible; }; + property.off = false == track_features::sleepers; property.empty = "of the model"; property.get = [](TTrack const &Track) { return Track.m_timber_skin_name; }; property.set = [](TTrack &Track, std::string const &Text) { @@ -810,7 +813,7 @@ std::size_t editor_mode::track_property_apply(int const Property, std::vector targets; for (auto *track : Tracks) - if (track != nullptr && false == track->m_editorremoved && property.applies(*track)) + if (track != nullptr && false == property.off && false == track->m_editorremoved && property.applies(*track)) targets.push_back(track); auto const changed{tracks_apply(targets, [&](TTrack &Track) { return property.set(Track, Text); }, property.rebuild, property.label)}; if (changed == 0 && targets.size() == 1) @@ -1231,6 +1234,7 @@ void editor_mode::render_track_properties(std::vector const &Tracks) if (list[i].part != Part || list[i].more != More || cache.applies[i] == 0) continue; ImGui::PushID(list[i].key); + ImGui::BeginDisabled(list[i].off); row_label(i); switch (list[i].kind) { @@ -1239,6 +1243,9 @@ void editor_mode::render_track_properties(std::vector const &Tracks) case field::texture: texture_row(i); break; default: text_row(i); break; } + ImGui::EndDisabled(); + if (list[i].off && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) + ImGui::SetTooltip("%s", STR_C("Switched off in this build of the simulator")); ImGui::PopID(); } ImGui::EndTable(); @@ -1285,7 +1292,7 @@ void editor_mode::copy_track_style(TTrack const &Track) style.values.clear(); style.from = name_of(Track); for (auto const &property : properties()) - if (property.applies(Track)) + if (false == property.off && property.applies(Track)) style.values.emplace_back(property.key, property.get(Track)); ui()->set_status(format(STR_C("Properties of %s copied: Ctrl+Shift+V pastes them on the selected tracks"), style.from.c_str()), false); } @@ -1306,7 +1313,7 @@ std::size_t editor_mode::paste_track_style(std::vector const &Tracks) if (index < 0) continue; auto const &property{list[index]}; - if (property.late != late || false == style.groups[property.group]) + if (property.off || property.late != late || false == style.groups[property.group]) continue; pasted.emplace_back(&property, value); rebuild |= property.rebuild; diff --git a/lang/editor_pl.po b/lang/editor_pl.po index af3611fa..8cebb007 100644 --- a/lang/editor_pl.po +++ b/lang/editor_pl.po @@ -10102,3 +10102,6 @@ msgstr "różnica wysokości %+.2f m pochylenie od %+.1f do %+.1f‰" msgid "grade %+.1f per mille" msgstr "pochylenie %+.1f‰" + +msgid "Switched off in this build of the simulator" +msgstr "Wyłączone w tej wersji symulatora"