diff --git a/application/editormodesignal.cpp b/application/editormodesignal.cpp index 2261dd47..7b875f04 100644 --- a/application/editormodesignal.cpp +++ b/application/editormodesignal.cpp @@ -980,6 +980,13 @@ std::size_t editor_mode::signal_batch(signal_changes const &Changes, std::vector items.push_back(std::move(placing)); reads.emplace_back(spot, variant->read.empty() ? std::string{} : editor_includes::substitute(variant->read, {order.name})); } + if (false == Error.empty()) + { + // nothing changed but the tracks cut for them, a step of undo + if (false == States.empty() || false == Created.empty()) + push_track_snapshot(std::move(States), std::move(Created)); + return 0; + } // the names passed round among the signals go through ones of their own first, or a read event renamed would be renamed again items.insert(items.end(), Changes.others.begin(), Changes.others.end()); EditorSnapshot step; diff --git a/application/editormodesrk.cpp b/application/editormodesrk.cpp index 7cc5e399..34661098 100644 --- a/application/editormodesrk.cpp +++ b/application/editormodesrk.cpp @@ -668,6 +668,17 @@ std::unordered_set guarded(std::vector const &Co return result; } +// a block signal standing by the track of the line facing its trains, Distance: how far out along it +bool block_along(station::line const &Line, standing_signal const &Signal, double &Distance) +{ + double gap{0.0}; + Distance = station::distance_on(Line, Signal.position, gap); + if (Signal.kind != "block" || gap > 4.5 || Distance < 50.0 || Distance > Line.length() - 1.0) + return false; + auto const way{station::point_on(Line, Distance).way}; + return (Line.inbound ? -1.0 : 1.0) * glm::dot(travel_of(Signal.yaw), glm::dvec2{way.x, way.z}) >= 0.87; +} + } // namespace srk_tool::shp_state srk_tool::head_check::shp_of() const @@ -1335,9 +1346,9 @@ void srk_tool::render_lines() auto changed{false}; if (ImGui::BeginTable("##srklinelist", 3, ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingStretchProp)) { - ImGui::TableSetupColumn(STR_C("Line"), ImGuiTableColumnFlags_WidthStretch, 0.27f); - ImGui::TableSetupColumn(STR_C("To"), ImGuiTableColumnFlags_WidthStretch, 0.33f); - ImGui::TableSetupColumn(STR_C("Block"), ImGuiTableColumnFlags_WidthStretch, 0.40f); + ImGui::TableSetupColumn(STR_C("Line"), ImGuiTableColumnFlags_WidthStretch, 0.26f); + ImGui::TableSetupColumn(STR_C("To"), ImGuiTableColumnFlags_WidthStretch, 0.29f); + ImGui::TableSetupColumn(STR_C("Block"), ImGuiTableColumnFlags_WidthStretch, 0.45f); ImGui::TableHeadersRow(); for (std::size_t index = 0; index < m_lines.size() && false == changed; ++index) { @@ -1481,7 +1492,7 @@ std::string srk_tool::boundary_hover(glm::dvec3 const &Point, bool &Valid) m_boundary.point = station::point_on(line, at).point; // the other track across, the block signals standing within reach on both std::vector> tracks{{static_cast(best), at}}; - if (row.partner >= 0 && row.partner < static_cast(m_line_ways.size())) + if (row.partner >= 0 && row.partner < static_cast(std::min(m_lines.size(), m_line_ways.size())) && false == m_lines[row.partner].legacy && m_lines[row.partner].block != block_kind::semi) if (double gap{0.0}; true) if (auto const across{station::distance_on(m_line_ways[row.partner], m_boundary.point, gap)}; gap < 12.0) tracks.emplace_back(static_cast(row.partner), across); @@ -1517,10 +1528,9 @@ std::string srk_tool::boundary_hover(glm::dvec3 const &Point, bool &Valid) continue; } auto const place{station::point_on(way, distance)}; - auto const number{km_line(way)}; m_boundary.places.push_back(place.point); m_boundary.ways.push_back(place.way); - m_boundary.names.push_back(station::block_number(km_along(way, number, distance), way.number, km_rising(way, number))); + m_boundary.names.push_back(station::block_number(km_along(way, other.km_number, distance), way.number, other.rising)); } std::string names; for (auto const &name : m_boundary.names) @@ -1532,7 +1542,7 @@ std::string srk_tool::boundary_hover(glm::dvec3 const &Point, bool &Valid) auto const least{row.block == block_kind::four ? row.braking * 0.5 : row.braking}; auto label{format(STR_C("Click: block signals %s here: the block sections %.2f km and %.2f km"), names.c_str(), (at - previous) / 1000.0, (next - at) / 1000.0)}; if (std::min(at - previous, next - at) < least) - label += "\n" + format(row.block == block_kind::four ? STR_C("shorter than half the braking distance, %.0f m, of the 4-aspect block") : STR_C("shorter than the braking distance, %.0f m"), least); + label += "\n" + format(row.block == block_kind::four ? STR_C("The block section of %.2f km is shorter than half the braking distance, %.0f m, of the 4-aspect block") : STR_C("The block section of %.2f km is shorter than the braking distance, %.0f m"), std::min(at - previous, next - at) / 1000.0, least); return label; } @@ -2408,9 +2418,10 @@ void srk_tool::set_signals() } } std::string error; + auto const touched{false == before.empty() || false == created.empty()}; auto const count{m_signals.signal_batch({placed, renamed, {}, {}, {}}, std::move(before), std::move(created), error)}; if (false == error.empty()) - m_status = format(STR_C("The signals couldn't be placed: %s"), error.c_str()); + m_status = format(STR_C("The signals couldn't be placed: %s"), error.c_str()) + (touched ? ". " + STR("Ctrl+Z takes back the tracks cut") : std::string{}); else m_status = format(STR_P("%zu signal placed", "%zu signals placed", count), count) + ", " + format(STR_P("%zu renamed", "%zu renamed", renamed.size()), renamed.size()); if (false == unfit.empty()) @@ -2590,12 +2601,13 @@ void srk_tool::survey_lines(std::vector const &Standing) row.travel = travel_of(Standing[owners[line.entry]].yaw); row.block = block_of(line, row.entry, Standing, heads, row.why, row.own, row.own_why, row.blocks); row.braking = line_braking(line); + row.km_number = km_line(line); + row.rising = km_rising(line, row.km_number); auto switched{false}; for (auto const &signal : Standing) { - double gap{0.0}; - auto const distance{station::distance_on(line, signal.position, gap)}; - if (signal.kind != "block" || gap > 4.5 || distance < 50.0 || distance > line.length() - 1.0) + double distance{0.0}; + if (false == block_along(line, signal, distance)) continue; row.stops.emplace_back(distance, signal_shown(signal.name, stem)); switched = switched || guards.count(ToLower(signal.name)) > 0; @@ -2666,11 +2678,8 @@ void srk_tool::set_lines(block_edit const *Edit) auto switched{false}; for (std::size_t k = 0; k < standing.size(); ++k) { - if (standing[k].kind != "block") - continue; - double gap{0.0}; - auto const distance{station::distance_on(line, standing[k].position, gap)}; - if (gap > 4.5 || distance < 50.0 || distance > line.length() - 1.0 || (line.inbound ? -1.0 : 1.0) * facing_out(line, standing[k], distance) < 0.87) + double distance{0.0}; + if (false == block_along(line, standing[k], distance)) continue; along[index].push_back(k); switched = switched || guards.count(ToLower(standing[k].name)) > 0; @@ -2702,7 +2711,10 @@ void srk_tool::set_lines(block_edit const *Edit) } processed[edited] = 1; if (auto const partner{lines[edited].partner}; partner >= 0 && automatic[partner] == 1) - processed[partner] = 1; + { + station::distance_on(lines[partner], station::point_on(lines[edited], drawn).point, gap); + processed[partner] = gap < 12.0 ? 1 : 0; + } } auto const described{line_of_open()}; double known{0.0}; @@ -3197,10 +3209,11 @@ void srk_tool::set_lines(block_edit const *Edit) return; } std::string error; + auto const touched{false == before.empty() || false == created.empty()}; m_signals.signal_batch(changes, std::move(before), std::move(created), error); if (false == error.empty()) { - m_status = format(STR_C("The signals couldn't be placed: %s"), error.c_str()); + m_status = format(STR_C("The signals couldn't be placed: %s"), error.c_str()) + (touched ? ". " + STR("Ctrl+Z takes back the tracks cut") : std::string{}); return; } m_status = format(STR_P("%zu block signal placed", "%zu block signals placed", blocks), blocks) + ", " + format(STR_P("%zu warning disc", "%zu warning discs", discs), discs) + ", " + @@ -3224,6 +3237,7 @@ void srk_tool::survey_signals() m_heads.clear(); m_heads_known = false; m_lines.clear(); + m_line_ways.clear(); m_lines_problem = STR("Looking for the signal templates..."); if (false == m_measured) measure({}); @@ -3642,7 +3656,7 @@ void srk_tool::set_shp() signal_changes changes; for (auto const &entry : places) { - auto *track{entry.track != nullptr ? entry.track : piece_at(entry.cut, entry.inside)}; + auto *track{entry.track != nullptr ? piece_at(entry.track, entry.point) : piece_at(entry.cut, entry.inside)}; // the trains run into the track at the point: at the start of its path running towards its end if (glm::distance(track->m_paths.front().points[entry.facing > 0 ? segment_data::point::start : segment_data::point::end], entry.point) > 1.0) { diff --git a/application/editormodesrk.h b/application/editormodesrk.h index 73810cf6..89399483 100644 --- a/application/editormodesrk.h +++ b/application/editormodesrk.h @@ -201,6 +201,8 @@ class srk_tool final : public editor_tool // block signals stand along it, none switched by block sections of the editor: it keeps the block of the scenery as it stands bool legacy{false}; double braking{0.0}; // m, the braking distance on it + std::string km_number; // the line of the kilometrage it runs along + bool rising{true}; // its trains run towards the higher km // the signals of the other block standing along it: warning discs on a line of the automatic block, block signals on one of the // semi-automatic one, the first of them std::size_t leftovers{0}; diff --git a/lang/editor_pl.po b/lang/editor_pl.po index 6b5d7ab3..5993edaa 100644 --- a/lang/editor_pl.po +++ b/lang/editor_pl.po @@ -11246,10 +11246,10 @@ msgid "LMB: fly to the first of them" msgstr "LPM: leć do pierwszego z nich" msgid "SBL, 3 aspects" -msgstr "SBL trzystawna" +msgstr "SBL 3-stawna" msgid "SBL, 4 aspects" -msgstr "SBL czterostawna" +msgstr "SBL 4-stawna" msgid "Automatic block, 3 aspects (SBL)" msgstr "Samoczynna blokada liniowa trzystawna (SBL)" @@ -11302,11 +11302,14 @@ msgstr "Klik: usuń semafory SBL %s, odstępy po obu stronach połączone: %.2f msgid "Click: block signals %s here: the block sections %.2f km and %.2f km" msgstr "Klik: semafory SBL %s tutaj, odstępy %.2f km i %.2f km" -msgid "shorter than half the braking distance, %.0f m, of the 4-aspect block" -msgstr "krótszy niż połowa drogi hamowania (%.0f m), a to SBL czterostawna" +msgid "The block section of %.2f km is shorter than half the braking distance, %.0f m, of the 4-aspect block" +msgstr "Odstęp %.2f km jest krótszy niż połowa drogi hamowania (%.0f m) przy SBL czterostawnej" -msgid "shorter than the braking distance, %.0f m" -msgstr "krótszy niż droga hamowania, %.0f m" +msgid "The block section of %.2f km is shorter than the braking distance, %.0f m" +msgstr "Odstęp %.2f km jest krótszy niż droga hamowania (%.0f m)" + +msgid "Ctrl+Z takes back the tracks cut" +msgstr "Ctrl+Z cofa przecięcia torów" msgid "The line drawn on isn't there any more" msgstr "Szlaku, na którym rysujesz, już nie ma"