mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-28 00:37:29 +01:00
feat(editor): the tracks are laid to the PKP PLK norms only: the choice of the free laying is gone, its cards in the panels of the laying and of the plan, the question as the laying starts and the setting; the transition curves and the cant of the norms always, the speed of the laying with its chips, the radius below the minimum for the speed a warning. The settings keep the radii the bends of the straights will be eased with instead
This commit is contained in:
@@ -657,7 +657,6 @@ bool editor_mode::init()
|
||||
{
|
||||
EditorSettings.load();
|
||||
Global.EditorOrthoTracks = EditorSettings.top_tracks();
|
||||
set_norms_free(EditorSettings.norms() == editorSettings::track_norms::free_laying);
|
||||
EditorModelSets.load();
|
||||
EditorTrackPresets.load();
|
||||
Camera.Init({0, 15, 0}, {glm::radians(-30.0), glm::radians(180.0), 0}, nullptr);
|
||||
@@ -1598,7 +1597,6 @@ bool editor_mode::update()
|
||||
render_open_scenery_popup();
|
||||
render_shortcuts_window();
|
||||
render_first_steps();
|
||||
render_norms_prompt();
|
||||
render_nmt_prompt();
|
||||
render_nmt_banner();
|
||||
render_orthophoto_window();
|
||||
@@ -1641,18 +1639,6 @@ void editor_mode::render_settings()
|
||||
ImGui::Separator();
|
||||
ImGui::Checkbox(STR_C("Transform gizmo (ImGuizmo)"), &m_gizmo_enabled);
|
||||
|
||||
ImGui::Separator();
|
||||
ImGui::TextUnformatted(STR_C("Laying of new tracks"));
|
||||
const char *norms[] = {STR_C("Ask as the laying starts"), STR_C("Free laying"), STR_C("To the PKP PLK norms")};
|
||||
int chosen = static_cast<int>(EditorSettings.norms());
|
||||
if (ImGui::Combo("##tracknorms", &chosen, norms, IM_ARRAYSIZE(norms)))
|
||||
{
|
||||
EditorSettings.norms(static_cast<editorSettings::track_norms>(chosen));
|
||||
EditorSettings.save();
|
||||
if (chosen > 0)
|
||||
set_norms_free(chosen == 1);
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
ImGui::TextUnformatted(STR_C("Colours of the editor"));
|
||||
const char *palettes[] = {STR_C("Green, as the rest of the simulator"), STR_C("Amber, of the editor")};
|
||||
|
||||
@@ -1070,7 +1070,7 @@ class editor_mode : public application_mode, private editor_track::observer, pri
|
||||
void render_route_stored();
|
||||
void route_update()
|
||||
{
|
||||
m_route.design.norms.checked = false == m_norms_free;
|
||||
m_route.design.norms.checked = true;
|
||||
m_route.result = alignment::compute(m_route.design);
|
||||
}
|
||||
void route_apply();
|
||||
@@ -1396,7 +1396,6 @@ class editor_mode : public application_mode, private editor_track::observer, pri
|
||||
std::string preview_error;
|
||||
double preview_length{0.0};
|
||||
double radius{500.0};
|
||||
bool transitions{false};
|
||||
double piece_length{100.0};
|
||||
bool copy_selected{false};
|
||||
editor_track::path_style style;
|
||||
@@ -1413,16 +1412,7 @@ class editor_mode : public application_mode, private editor_track::observer, pri
|
||||
std::size_t history{0}; // the step of the history the chain was begun at
|
||||
};
|
||||
lay_tool m_lay;
|
||||
bool m_norms_free{false};
|
||||
// the choice between the free laying and the norms, asked once a session as the laying or the plan is opened first
|
||||
bool m_norms_prompt{false};
|
||||
bool m_norms_asked{false};
|
||||
bool m_norms_remember{false};
|
||||
alignment::limits laying_norms() const;
|
||||
// returns: a card was clicked
|
||||
bool render_norms_choice();
|
||||
void render_norms_prompt();
|
||||
void set_norms_free(bool const Free);
|
||||
glm::dvec3 lay_angle_snap(glm::dvec3 const &Mouse, std::string &Label) const;
|
||||
// the straight track Alt turns the laid straight to: the nearest one the straight from From to To crosses, or one along From
|
||||
TTrack const *skew_reference(glm::dvec3 const &From, glm::dvec3 const &To, double const Reach) const;
|
||||
@@ -1546,7 +1536,7 @@ class editor_mode : public application_mode, private editor_track::observer, pri
|
||||
TTrack const *m_join_track{nullptr};
|
||||
editor_track::point_ref m_join_point;
|
||||
mutable alignment::join_result m_join_last;
|
||||
// the layout laid on from the end of From with the transition curves of the norms; none in the free laying, or where it doesn't fit
|
||||
// the layout laid on from the end of From with the transition curves of the norms; none where it doesn't fit
|
||||
std::optional<alignment::lay_result> eased_layout(TTrack const *From, glm::dvec3 const &Point, glm::dvec2 const &Direction, glm::dvec3 const &Target, double const Radius) const;
|
||||
mutable std::optional<alignment::lay_result> m_eased_last;
|
||||
mutable std::optional<std::pair<alignment::lay_request, std::optional<alignment::lay_result>>> m_eased_cache;
|
||||
|
||||
@@ -426,7 +426,7 @@ void editor_mode::point_drag_finish()
|
||||
std::optional<alignment::lay_result> editor_mode::eased_layout(TTrack const *From, glm::dvec3 const &Point, glm::dvec2 const &Direction, glm::dvec3 const &Target, double const Radius) const
|
||||
{
|
||||
m_eased_last.reset();
|
||||
if (false == m_lay.transitions || From == nullptr || From->eType != tt_Normal)
|
||||
if (From == nullptr || From->eType != tt_Normal)
|
||||
return std::nullopt;
|
||||
auto const end{editor_track::bend_at(*From, Point)};
|
||||
if (false == end.has_value())
|
||||
@@ -571,13 +571,13 @@ std::vector<segment_data> editor_mode::join_pieces(TTrack const *From, editor_tr
|
||||
request.end.roll = End.track != nullptr ? editor_track::joint_roll(*End.track, End.point) : 0.0;
|
||||
request.radius = m_join_radius;
|
||||
request.variant = m_join_variant;
|
||||
request.transitions = m_lay.transitions;
|
||||
request.transitions = true;
|
||||
request.speed = design_speed(From, End.track);
|
||||
request.kink = m_joints.kink_angle() * 0.5;
|
||||
request.shape = m_route.design.shape;
|
||||
request.norms = laying_norms();
|
||||
auto result{alignment::join(request)};
|
||||
if (m_lay.transitions && result.kind != alignment::join_kind::straight && result.kind != alignment::join_kind::arc && glm::length(request.end.direction) > 1e-9)
|
||||
if (result.kind != alignment::join_kind::straight && result.kind != alignment::join_kind::arc && glm::length(request.end.direction) > 1e-9)
|
||||
{
|
||||
auto const grade{(End.position.y - Start.y) / std::max(1.0, plan_distance(Start, End.position))};
|
||||
auto const in{From != nullptr && From->eType == tt_Normal ? editor_track::ease_out_of(*From, Start, grade, request.speed, request.norms) : editor_track::easing{}};
|
||||
@@ -989,8 +989,8 @@ std::vector<segment_data> editor_mode::lay_pieces(std::vector<glm::dvec3> const
|
||||
result.pieces.clear();
|
||||
return result;
|
||||
};
|
||||
auto const in{tool.transitions ? eased(tool.start, 0.0, 1.0) : editor_track::easing{}};
|
||||
auto const out{tool.transitions ? eased(End, shape.length, -1.0) : editor_track::easing{}};
|
||||
auto const in{eased(tool.start, 0.0, 1.0)};
|
||||
auto const out{eased(End, shape.length, -1.0)};
|
||||
if ((false == in.pieces.empty() || false == out.pieces.empty()) && editor_track::eases_room(in, out, Points.front(), design.start_direction, Points.back(), design.end_direction))
|
||||
{
|
||||
auto points{Points};
|
||||
@@ -1063,7 +1063,7 @@ alignment::result editor_mode::lay_shape(std::vector<glm::dvec3> const &Points,
|
||||
design.vertices.back().offset = std::max(1.0, glm::dot(plan_of(Points.back() - Points[Points.size() - 2]), design.end_direction));
|
||||
}
|
||||
}
|
||||
return alignment::compute_recommended(design, tool.transitions);
|
||||
return alignment::compute_recommended(design, true);
|
||||
}
|
||||
|
||||
void editor_mode::lay_click()
|
||||
@@ -1360,202 +1360,26 @@ editor_mode::track_hover editor_mode::split_spot() const
|
||||
alignment::limits editor_mode::laying_norms() const
|
||||
{
|
||||
auto norms{m_route.design.norms};
|
||||
norms.checked = false == m_norms_free;
|
||||
norms.checked = true;
|
||||
return norms;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// a card of the geometry of the new track: its plan, and under it its curvature along the length, a point running along both;
|
||||
// a plain arc jumps to its curvature, a railway curve leads into it along a transition, the cant with it
|
||||
float geometry_card_height(char const *Title, char const *Text, float const Width)
|
||||
{
|
||||
auto const font{ImGui::GetFontSize()};
|
||||
auto const pad{std::round(font * 0.5f)};
|
||||
auto const wrap{Width - 2.0f * pad};
|
||||
return pad + ImGui::CalcTextSize(Title, nullptr, false, wrap).y + pad * 0.5f + std::round(font * 2.6f) + pad * 0.5f + ImGui::CalcTextSize(Text, nullptr, false, wrap).y + pad;
|
||||
}
|
||||
|
||||
bool geometry_card(char const *Id, char const *Title, char const *Text, bool const Railway, bool const Chosen, float const Width, float const Height)
|
||||
{
|
||||
auto const font{ImGui::GetFontSize()};
|
||||
auto const pad{std::round(font * 0.5f)};
|
||||
auto const sketch{std::round(font * 2.6f)};
|
||||
auto const wrap{Width - 2.0f * pad};
|
||||
auto const title{ImGui::CalcTextSize(Title, nullptr, false, wrap)};
|
||||
auto const height{Height};
|
||||
auto const top{ImGui::GetCursorScreenPos()};
|
||||
auto const clicked{ImGui::InvisibleButton(Id, ImVec2(Width, height))};
|
||||
auto const hovered{ImGui::IsItemHovered()};
|
||||
auto *list{ImGui::GetWindowDrawList()};
|
||||
auto const accent{family_colour(0)};
|
||||
ImVec2 const bottom{top.x + Width, top.y + height};
|
||||
auto const rounding{std::round(font * 0.35f)};
|
||||
list->AddRectFilled(top, bottom, Chosen ? (accent & ~IM_COL32_A_MASK) | IM_COL32(0, 0, 0, 46) : ImGui::GetColorU32(hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), rounding);
|
||||
list->AddRect(top, bottom, Chosen ? accent : ImGui::GetColorU32(ImGuiCol_Border), rounding, 0, Chosen ? 2.0f : 1.0f);
|
||||
auto y{top.y + pad};
|
||||
list->AddText(nullptr, 0.0f, ImVec2(top.x + pad, y), ImGui::GetColorU32(ImGuiCol_Text), Title, nullptr, wrap);
|
||||
y += title.y + pad * 0.5f;
|
||||
// the curvature along the length, as a share of the curvature of the arc
|
||||
auto const curvature = [Railway](double const Share) {
|
||||
if (Railway)
|
||||
return std::clamp((Share - 0.22) / 0.3, 0.0, 1.0);
|
||||
return Share < 0.37 ? 0.0 : 1.0;
|
||||
};
|
||||
int constexpr steps{80};
|
||||
std::vector<ImVec2> plan;
|
||||
plan.reserve(steps + 1);
|
||||
double heading{0.0}, px{0.0}, py{0.0};
|
||||
auto const turn{1.45 / (Railway ? 0.63 - 0.15 : 0.63)};
|
||||
for (int i = 0; i <= steps; ++i)
|
||||
{
|
||||
plan.emplace_back(static_cast<float>(px), static_cast<float>(py));
|
||||
auto const share{(i + 0.5) / steps};
|
||||
heading += curvature(share) * turn / steps;
|
||||
px += std::cos(heading) / steps;
|
||||
py -= std::sin(heading) / steps;
|
||||
}
|
||||
ImVec2 low{plan.front()}, high{plan.front()};
|
||||
for (auto const &point : plan)
|
||||
{
|
||||
low = ImVec2(std::min(low.x, point.x), std::min(low.y, point.y));
|
||||
high = ImVec2(std::max(high.x, point.x), std::max(high.y, point.y));
|
||||
}
|
||||
// the plan on the left, the curvature along the length on the right
|
||||
auto const half{std::floor((wrap - pad) * 0.5f)};
|
||||
auto const scale{std::min(half / std::max(1e-3f, high.x - low.x), sketch / std::max(1e-3f, high.y - low.y))};
|
||||
ImVec2 const origin{top.x + pad + (half - (high.x - low.x) * scale) * 0.5f, y + sketch - (high.y - low.y) * scale};
|
||||
for (auto &point : plan)
|
||||
point = ImVec2(origin.x + (point.x - low.x) * scale, origin.y + (point.y - low.y) * scale);
|
||||
auto const line{Chosen ? accent : ImGui::GetColorU32(ImGuiCol_Text, 0.75f)};
|
||||
list->AddPolyline(plan.data(), static_cast<int>(plan.size()), line, 0, 2.0f);
|
||||
auto const label{ImGui::CalcTextSize("1/R")};
|
||||
auto const graph_left{top.x + pad + half + pad * 0.5f + label.x + 2.0f};
|
||||
auto const graph_width{top.x + pad + wrap - graph_left};
|
||||
auto const graph_top{y};
|
||||
auto const graph{sketch};
|
||||
auto const axis{ImGui::GetColorU32(ImGuiCol_TextDisabled, 0.6f)};
|
||||
list->AddLine(ImVec2(graph_left, graph_top + graph), ImVec2(graph_left + graph_width, graph_top + graph), axis);
|
||||
list->AddLine(ImVec2(graph_left, graph_top), ImVec2(graph_left, graph_top + graph), axis);
|
||||
list->AddText(ImVec2(graph_left - label.x - 2.0f, graph_top + graph * 0.2f - label.y * 0.5f), axis, "1/R");
|
||||
std::vector<ImVec2> curve;
|
||||
for (int i = 0; i <= steps; ++i)
|
||||
{
|
||||
auto const share{static_cast<double>(i) / steps};
|
||||
curve.emplace_back(graph_left + static_cast<float>(share) * graph_width, graph_top + graph - static_cast<float>(curvature(share)) * graph * 0.8f);
|
||||
}
|
||||
list->AddPolyline(curve.data(), static_cast<int>(curve.size()), line, 0, 1.5f);
|
||||
if (Railway)
|
||||
for (int i = 0; i < steps; i += 4)
|
||||
{
|
||||
auto const share{static_cast<double>(i) / steps};
|
||||
auto const next{static_cast<double>(i + 2) / steps};
|
||||
list->AddLine(ImVec2(graph_left + static_cast<float>(share) * graph_width, graph_top + graph - static_cast<float>(curvature(share)) * graph * 0.45f),
|
||||
ImVec2(graph_left + static_cast<float>(next) * graph_width, graph_top + graph - static_cast<float>(curvature(next)) * graph * 0.45f), IM_COL32(240, 170, 60, 220), 1.0f);
|
||||
}
|
||||
auto const running{std::fmod(ImGui::GetTime() * 0.22, 1.0)};
|
||||
auto const index{std::clamp(static_cast<int>(running * steps), 0, steps)};
|
||||
list->AddCircleFilled(plan[index], 3.0f, IM_COL32(255, 255, 255, 230));
|
||||
list->AddLine(ImVec2(curve[index].x, graph_top), ImVec2(curve[index].x, graph_top + graph), IM_COL32(255, 255, 255, 70));
|
||||
list->AddCircleFilled(curve[index], 2.5f, IM_COL32(255, 255, 255, 230));
|
||||
y += sketch + pad * 0.5f;
|
||||
list->AddText(nullptr, 0.0f, ImVec2(top.x + pad, y), ImGui::GetColorU32(ImGuiCol_TextDisabled), Text, nullptr, wrap);
|
||||
return clicked;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool editor_mode::render_norms_choice()
|
||||
{
|
||||
auto picked{false};
|
||||
auto const gap{std::round(ImGui::GetFontSize() * 0.5f)};
|
||||
auto const width{std::floor((ImGui::GetContentRegionAvail().x - gap) * 0.5f)};
|
||||
char const *const titles[]{STR_C("Free laying"), STR_C("To the PKP PLK norms")};
|
||||
char const *const texts[]{STR_C("Plain arcs, no transition curves nor cant"), STR_C("Transition curves and cant for the speed, checked against the norms")};
|
||||
auto const height{std::max(geometry_card_height(titles[0], texts[0], width), geometry_card_height(titles[1], texts[1], width))};
|
||||
ImGui::PushID("geometry");
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
if (i > 0)
|
||||
ImGui::SameLine(0.0f, gap);
|
||||
auto const chosen{m_norms_free == (i == 0)};
|
||||
auto const clicked{geometry_card(i == 0 ? "##free" : "##norms", titles[i], texts[i], i == 1, chosen, width, height)};
|
||||
item_tooltip(i == 0 ? "Plain arcs with no transition curves and no cant, no warnings about the norms: the track goes where it's clicked"
|
||||
: "Transition curves and cant for the design speed, warnings when the radius, the cant or the transitions don't meet the norms");
|
||||
picked |= clicked;
|
||||
if (clicked && false == chosen)
|
||||
{
|
||||
set_norms_free(i == 0);
|
||||
// a kept choice follows the one made later
|
||||
if (EditorSettings.norms() != editorSettings::track_norms::ask)
|
||||
{
|
||||
EditorSettings.norms(m_norms_free ? editorSettings::track_norms::free_laying : editorSettings::track_norms::plk);
|
||||
EditorSettings.save();
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::PopID();
|
||||
return picked;
|
||||
}
|
||||
|
||||
void editor_mode::render_norms_prompt()
|
||||
{
|
||||
if (false == m_norms_prompt)
|
||||
return;
|
||||
char const *const title{STR_C("How to lay the tracks###normsprompt")};
|
||||
if (false == ImGui::IsPopupOpen(title))
|
||||
ImGui::OpenPopup(title);
|
||||
ImGui::SetNextWindowSize(ImVec2(520.0f * Global.ui_scale, 0.0f));
|
||||
if (false == ImGui::BeginPopupModal(title, nullptr, ImGuiWindowFlags_NoResize))
|
||||
return;
|
||||
ImGui::TextWrapped("%s", STR_C("Choose how the new tracks are laid. It can be changed any time at the top of the panels of laying and of the plan."));
|
||||
ImGui::Spacing();
|
||||
if (render_norms_choice())
|
||||
{
|
||||
if (m_norms_remember)
|
||||
{
|
||||
EditorSettings.norms(m_norms_free ? editorSettings::track_norms::free_laying : editorSettings::track_norms::plk);
|
||||
EditorSettings.save();
|
||||
}
|
||||
m_norms_prompt = false;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::Spacing();
|
||||
ImGui::Checkbox(STR_C("Remember the choice, don't ask again"), &m_norms_remember);
|
||||
item_tooltip("Asking again can be switched on in the settings of the editor (General)");
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
void editor_mode::set_norms_free(bool const Free)
|
||||
{
|
||||
m_norms_free = Free;
|
||||
m_lay.transitions = false == m_norms_free;
|
||||
if (false == m_route.chain.tracks.empty())
|
||||
route_update();
|
||||
}
|
||||
|
||||
void editor_mode::render_lay_ui()
|
||||
{
|
||||
auto &tool{m_lay};
|
||||
render_norms_choice();
|
||||
ImGui::Separator();
|
||||
ImGui::PushItemWidth(120.0f);
|
||||
ImGui::DragScalar(STR_C("Curve radius (m)"), ImGuiDataType_Double, &tool.radius, 5.0f, nullptr, nullptr, "%.0f");
|
||||
item_tooltip("Drag to change, Ctrl+click to type the value. While laying: Ctrl+wheel");
|
||||
value_chips("radii", tool.radius, {190.0, 300.0, 500.0, 800.0, 1200.0, 2000.0}, "%.0f");
|
||||
tool.radius = std::max(10.0, tool.radius);
|
||||
ImGui::DragScalar(STR_C("Speed (km/h)"), ImGuiDataType_Double, &tool.style.velocity, 1.0f, nullptr, nullptr, "%.0f");
|
||||
item_tooltip(m_norms_free ? "Speed limit of the new paths; the speed of the track joined comes first"
|
||||
: "Speed limit of the new paths, and the design speed of the transition curves and of the cant; the speed of the track joined comes first, and none higher than the radius allows");
|
||||
if (false == m_norms_free)
|
||||
value_chips("speeds", tool.style.velocity, {40.0, 60.0, 80.0, 100.0, 120.0, 160.0}, "%.0f");
|
||||
item_tooltip("Speed limit of the new paths, and the design speed of the transition curves and of the cant; the speed of the track joined comes first, and none higher than the radius allows");
|
||||
value_chips("speeds", tool.style.velocity, {40.0, 60.0, 80.0, 100.0, 120.0, 160.0}, "%.0f");
|
||||
tool.style.velocity = std::clamp(tool.style.velocity, 0.0, 400.0);
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::Checkbox(STR_C("This speed also on from a track with its own"), &tool.own_speed);
|
||||
item_tooltip(m_norms_free ? "Off: a track laid on from another one, or joined to it, takes the speed of that track.\nOn: the new tracks get the speed above"
|
||||
: "Off: a track laid on from another one, or joined to it, is designed for the speed of that track and takes it.\nOn: it's designed for the speed above and the new tracks get it.\nWhile laying: Ctrl+Shift+wheel");
|
||||
if (auto const [from, to]{laying_ends()}; false == m_norms_free && (from != nullptr || to != nullptr))
|
||||
item_tooltip("Off: a track laid on from another one, or joined to it, is designed for the speed of that track and takes it.\nOn: it's designed for the speed above and the new tracks get it.\nWhile laying: Ctrl+Shift+wheel");
|
||||
if (auto const [from, to]{laying_ends()}; from != nullptr || to != nullptr)
|
||||
ImGui::TextDisabled("%s", design_speed_of(from, to).c_str());
|
||||
ImGui::TextDisabled("%s", STR_C("Height of the track on the ground"));
|
||||
if (int heights{static_cast<int>(EditorSettings.heights())};
|
||||
|
||||
@@ -1551,7 +1551,7 @@ void editor_mode::nmt_place_scenery(glm::dvec2 const &Point)
|
||||
void editor_mode::nmt_offer()
|
||||
{
|
||||
auto &state{m_nmt_state};
|
||||
if (state.offered || m_norms_prompt || false == m_lay.active || false == EditorSettings.terrain_offer())
|
||||
if (state.offered || false == m_lay.active || false == EditorSettings.terrain_offer())
|
||||
return;
|
||||
state.offered = true;
|
||||
if (m_streamer.resident() > 0 || std::any_of(simulation::Paths.sequence().begin(), simulation::Paths.sequence().end(), [](TTrack const *Track) { return Track != nullptr && rail(*Track); }))
|
||||
|
||||
@@ -1345,8 +1345,6 @@ void editor_mode::render_route_gizmo()
|
||||
void editor_mode::render_route_ui()
|
||||
{
|
||||
auto &route{m_route};
|
||||
render_norms_choice();
|
||||
ImGui::Separator();
|
||||
if (false == route.error.empty())
|
||||
ImGui::TextColored(ImVec4(1.0f, 0.35f, 0.3f, 1.0f), "%s", route.error.c_str());
|
||||
if (route.chain.tracks.empty())
|
||||
@@ -1805,7 +1803,6 @@ bool editor_mode::render_route_vertex(int const Index)
|
||||
vertex.transition_in = std::max(0.0, vertex.transition_in);
|
||||
vertex.transition_out = std::max(0.0, vertex.transition_out);
|
||||
vertex.cant = std::max(0.0, vertex.cant);
|
||||
if (false == m_norms_free)
|
||||
{
|
||||
if (ImGui::SmallButton(STR_C("Apply recommended for V")))
|
||||
{
|
||||
|
||||
@@ -182,8 +182,6 @@ void editor_mode::selftest_step()
|
||||
if (false == line.empty() && line.front() != '#')
|
||||
test.lines.push_back(line);
|
||||
WriteLog("SELFTEST: " + std::to_string(test.lines.size()) + " steps from " + file);
|
||||
// the scripts were written for the free laying, "norms plk" takes the norms
|
||||
set_norms_free(true);
|
||||
}
|
||||
++editor_selftest::frames();
|
||||
// how long each frame took, for the longest one perf tells
|
||||
|
||||
@@ -61,6 +61,7 @@ editor_mode::selftest_result editor_mode::selftest_join(std::string const &comma
|
||||
double height{0.0};
|
||||
if (command == "join")
|
||||
{
|
||||
// the transitions word left from the free laying: they follow the norms
|
||||
words >> radius >> variant >> transitions;
|
||||
// of the ends, for sceneries far above zero
|
||||
if (words >> height)
|
||||
@@ -86,7 +87,6 @@ editor_mode::selftest_result editor_mode::selftest_join(std::string const &comma
|
||||
}
|
||||
m_join_radius = radius;
|
||||
m_join_variant = variant;
|
||||
m_lay.transitions = transitions != 0;
|
||||
pieces = join_pieces(tool.track, from.point, tool.point, tool.direction, to, length, error);
|
||||
}
|
||||
else
|
||||
@@ -168,10 +168,8 @@ editor_mode::selftest_result editor_mode::selftest_join(std::string const &comma
|
||||
}
|
||||
if (command == "norms")
|
||||
{
|
||||
std::string which;
|
||||
words >> which;
|
||||
set_norms_free(which != "plk");
|
||||
WriteLog(std::string{"SELFTEST norms: "} + (m_norms_free ? "free" : "plk"));
|
||||
// the tracks are laid to the norms only
|
||||
WriteLog("SELFTEST norms: plk");
|
||||
return selftest_result::handled;
|
||||
}
|
||||
if (command == "layspeed")
|
||||
|
||||
@@ -442,8 +442,7 @@ void editor_mode::render_straight_ui()
|
||||
ImGui::TextDisabled("%s", STR_C("Transition curves"));
|
||||
int transitions{state.auto_transitions ? 0 : 1};
|
||||
if (segmented("straighttransitions", transitions,
|
||||
{m_norms_free ? segment_option{0, STR_C("None"), "Plain arcs: the free design has no transition curves, the PKP PLK norms work them out from the speed of the line"}
|
||||
: segment_option{0, STR_C("From the line speed"), "Lengths of the transition curves from the speed of the paths and the limits of the curve design"},
|
||||
{{0, STR_C("From the line speed"), "Lengths of the transition curves from the speed of the paths and the limits of the curve design"},
|
||||
{1, STR_C("Given length"), "The same length of the transition curves at every curve"}}))
|
||||
state.auto_transitions = transitions == 0;
|
||||
if (false == state.auto_transitions)
|
||||
|
||||
@@ -493,11 +493,6 @@ void editor_mode::show_track_tab(track_tab const Wanted)
|
||||
m_switch.armed = -1;
|
||||
m_signal.armed = false;
|
||||
m_track_tab = Tab;
|
||||
if ((Tab == track_tab::lay || Tab == track_tab::straights || Tab == track_tab::route) && false == m_norms_asked && EditorSettings.norms() == editorSettings::track_norms::ask && std::getenv("EU07_EDITOR_SELFTEST") == nullptr)
|
||||
{
|
||||
m_norms_asked = true;
|
||||
m_norms_prompt = true;
|
||||
}
|
||||
auto *track{selected_track()};
|
||||
switch (Tab)
|
||||
{
|
||||
@@ -1854,8 +1849,7 @@ std::string editor_mode::track_readout() const
|
||||
auto text{radius > 0.0 ? format("L %.2f m R %.0f m", length, radius) + speed_of(radius, laying_norms()) : format("L %.2f m %s", length, STR_C("straight"))};
|
||||
if (auto const eased{eased_of(m_eased_last)}; false == eased.empty())
|
||||
text += "\n" + eased;
|
||||
if (false == m_norms_free)
|
||||
text += "\n" + design_speed_of(m_extend.track, snapped ? target.track : nullptr);
|
||||
text += "\n" + design_speed_of(m_extend.track, snapped ? target.track : nullptr);
|
||||
if (auto const vertical{vertical_of(pieces)}; false == vertical.empty())
|
||||
text += "\n" + vertical;
|
||||
if (snapped)
|
||||
@@ -1890,7 +1884,6 @@ std::string editor_mode::track_readout() const
|
||||
text = format("L %.1f m %s", lay.preview_length, STR_C("straight"));
|
||||
if (auto const eased{eased_of(m_eased_last)}; false == eased.empty())
|
||||
text += "\n" + eased;
|
||||
if (false == m_norms_free)
|
||||
{
|
||||
auto const [from, to]{laying_ends()};
|
||||
text += "\n" + design_speed_of(from, to);
|
||||
@@ -2009,7 +2002,7 @@ std::string editor_mode::track_shaping(bool const Joined) const
|
||||
auto text{std::string{STR_C(names[static_cast<int>(m_track_layout)])}};
|
||||
if (m_track_layout == track_layout::arc_straight || m_track_layout == track_layout::straight_arc)
|
||||
text += format(" R %.0f m", m_lay.radius);
|
||||
return text + "\n" + STR("Ctrl+wheel: radius, Shift+wheel: arc / straight") + (m_norms_free ? std::string{} : STR(", Ctrl+Shift+wheel: speed"));
|
||||
return text + "\n" + STR("Ctrl+wheel: radius, Shift+wheel: arc / straight") + STR(", Ctrl+Shift+wheel: speed");
|
||||
}
|
||||
auto const &join{m_join_last};
|
||||
char const *const kinds[]{"", "straight", "arc", "curve", "reverse curve", "free curve"};
|
||||
@@ -2024,7 +2017,7 @@ std::string editor_mode::track_shaping(bool const Joined) const
|
||||
text += format(" V %.0f km/h", join.speed);
|
||||
if (join.variants > 1)
|
||||
text += format(" %d/%d", (m_join_variant % join.variants + join.variants) % join.variants + 1, join.variants);
|
||||
return text + "\n" + STR("Ctrl+wheel: radius, Shift+wheel: another shape") + (m_norms_free ? std::string{} : STR(", Ctrl+Shift+wheel: speed"));
|
||||
return text + "\n" + STR("Ctrl+wheel: radius, Shift+wheel: another shape") + STR(", Ctrl+Shift+wheel: speed");
|
||||
}
|
||||
|
||||
void editor_mode::draw_empty_scenery_hint()
|
||||
|
||||
@@ -114,8 +114,18 @@ bool editorSettings::load()
|
||||
m_top_tracks = std::clamp(std::atoi(value.c_str()), 0, 2);
|
||||
else if (key == "top_rails")
|
||||
m_top_rails = static_cast<std::uint32_t>(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 == "corner_radii")
|
||||
{
|
||||
// low;high
|
||||
double low{0.0}, high{0.0};
|
||||
if (auto const separator{value.find(';')}; separator != std::string::npos)
|
||||
{
|
||||
parse(value.substr(0, separator), low);
|
||||
parse(value.substr(separator + 1), high);
|
||||
if (low >= 10.0 && high >= low)
|
||||
corners(low, high);
|
||||
}
|
||||
}
|
||||
// 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")
|
||||
@@ -168,7 +178,7 @@ bool editorSettings::save()
|
||||
stream << "track_tools_all " << (m_track_tools_more ? 1 : 0) << "\n";
|
||||
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 << "corner_radii " << m_corner_low << ";" << m_corner_high << "\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)
|
||||
|
||||
@@ -67,15 +67,14 @@ public:
|
||||
void top_tracks(int const Tracks) { m_top_tracks = Tracks; }
|
||||
std::uint32_t top_rails() const { return m_top_rails; }
|
||||
void top_rails(std::uint32_t const Colour) { m_top_rails = Colour; }
|
||||
// how the new tracks are laid: asked as the laying starts, or the choice kept
|
||||
enum class track_norms
|
||||
// the radii the laying from point to point eases the bends of the straights with, at the peak of the two transition curves
|
||||
double corner_low() const { return m_corner_low; }
|
||||
double corner_high() const { return m_corner_high; }
|
||||
void corners(double const Low, double const High)
|
||||
{
|
||||
ask,
|
||||
free_laying,
|
||||
plk
|
||||
};
|
||||
track_norms norms() const { return m_norms; }
|
||||
void norms(track_norms Norms) { m_norms = Norms; }
|
||||
m_corner_low = Low;
|
||||
m_corner_high = High;
|
||||
}
|
||||
// the heights of the tracks laid on the ground: fitted to it as the tracks go onto the terrain, the points clicked on it with
|
||||
// even grades between them, level
|
||||
enum class lay_heights
|
||||
@@ -101,7 +100,8 @@ private:
|
||||
bool m_track_tools_more{false};
|
||||
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};
|
||||
double m_corner_low{3000.0};
|
||||
double m_corner_high{6000.0};
|
||||
lay_heights m_heights{lay_heights::points};
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user