17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-31 00:50:29 +01:00

feat(editor): the top view draws the tracks whole, without the ballast or the rails alone, in a colour of their own over the imagery and the map: both rails close up, one line further out; a choice by the extent and in the View menu, kept in the settings

This commit is contained in:
maj00r
2026-10-23 13:20:06 +02:00
parent fe3dd758ea
commit a892532fda
9 changed files with 137 additions and 27 deletions

View File

@@ -645,7 +645,7 @@ editor_ui *editor_mode::ui() const
bool editor_mode::init()
{
EditorSettings.load();
Global.EditorOrthoBallast = EditorSettings.top_ballast();
Global.EditorOrthoTracks = EditorSettings.top_tracks();
set_norms_free(EditorSettings.norms() == editorSettings::track_norms::free_laying);
EditorModelSets.load();
Camera.Init({0, 15, 0}, {glm::radians(-30.0), glm::radians(180.0), 0}, nullptr);
@@ -1486,6 +1486,8 @@ bool editor_mode::update()
draw_track_labels();
draw_track_legend();
}
else if (Global.EditorOrtho && Global.EditorOrthoTracks > 1)
draw_track_lines();
if (selected_track())
draw_track_overlay();
if (route_active())
@@ -3627,13 +3629,11 @@ void editor_mode::render_view_menu()
toggle_ortho();
if (ImGui::IsItemHovered())
ImGui::SetTooltip("%s", STR_C("The view straight down without perspective, as on a map; again for the camera as it was"));
if (ImGui::MenuItem(STR_C("Ballast in the top view"), nullptr, &Global.EditorOrthoBallast))
if (ImGui::BeginMenu(STR_C("Tracks in the top view")))
{
EditorSettings.top_ballast(Global.EditorOrthoBallast);
EditorSettings.save();
render_top_tracks_choice(false);
ImGui::EndMenu();
}
if (ImGui::IsItemHovered())
ImGui::SetTooltip("%s", STR_C("Off: the top view draws the rails and sleepers of the tracks without the ballast, so the ground under them shows"));
if (ImGui::BeginMenu(STR_C("Track colours")))
{
char const *const names[]{"Plain", "By the radius", "By the speed", "By the grade"};
@@ -5656,13 +5656,7 @@ void editor_mode::render_gizmo_options()
if (ImGui::IsItemHovered())
ImGui::SetTooltip("%s", STR_C("Wheel zooms. Hold the wheel and drag to pan."));
ImGui::SameLine();
if (ImGui::Checkbox(STR_C("Ballast"), &Global.EditorOrthoBallast))
{
EditorSettings.top_ballast(Global.EditorOrthoBallast);
EditorSettings.save();
}
if (ImGui::IsItemHovered())
ImGui::SetTooltip("%s", STR_C("Off: the top view draws the rails and sleepers of the tracks without the ballast, so the ground under them shows"));
render_top_tracks_choice(true);
}
if (ui()->mode() == nodebank_panel::TRACK && m_track_tab != track_tab::path && m_track_tab != track_tab::turnout && m_track_tab != track_tab::turntable && m_track_tab != track_tab::srk &&
m_track_tab != track_tab::lineside)
@@ -6999,3 +6993,51 @@ void editor_mode::starter_trainset(std::vector<std::string> &Trailing)
return;
}
}
void editor_mode::render_top_tracks_choice(bool const Combo)
{
static char const *const labels[]{"Whole", "Without ballast", "Rails only"};
static char const *const tooltips[]{"The tracks as in the 3D view", "The rails and the sleepers, the ground under them shows", "The rails alone, without the sleepers and the timbers of the switches, as on a plan"};
auto chosen{std::clamp(Global.EditorOrthoTracks, 0, 2)};
auto const pick = [&](int const Choice) {
Global.EditorOrthoTracks = Choice;
EditorSettings.top_tracks(Choice);
EditorSettings.save();
};
if (false == Combo)
{
for (int choice = 0; choice < 3; ++choice)
{
if (ImGui::MenuItem(STR_C(labels[choice]), nullptr, chosen == choice))
pick(choice);
if (ImGui::IsItemHovered())
ImGui::SetTooltip("%s", STR_C(tooltips[choice]));
}
return;
}
ImGui::SetNextItemWidth(130.0f);
if (ImGui::BeginCombo(STR_C("Tracks"), STR_C(labels[chosen])))
{
for (int choice = 0; choice < 3; ++choice)
{
if (ImGui::Selectable(STR_C(labels[choice]), chosen == choice))
pick(choice);
if (ImGui::IsItemHovered())
ImGui::SetTooltip("%s", STR_C(tooltips[choice]));
}
ImGui::EndCombo();
}
if (ImGui::IsItemHovered())
ImGui::SetTooltip("%s", STR_C("How the top view draws the tracks"));
if (chosen < 2)
return;
ImGui::SameLine();
auto colour{ImGui::ColorConvertU32ToFloat4(EditorSettings.top_rails())};
if (ImGui::ColorEdit3("##toprails", &colour.x, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel))
{
EditorSettings.top_rails(ImGui::ColorConvertFloat4ToU32(ImVec4(colour.x, colour.y, colour.z, 1.0f)));
EditorSettings.save();
}
if (ImGui::IsItemHovered())
ImGui::SetTooltip("%s", STR_C("The colour of the rails, to stand out on the imagery and the map"));
}

View File

@@ -765,6 +765,8 @@ class editor_mode : public application_mode, private editor_track::observer, pri
void render_gizmo();
// gizmo settings, drawn in the toolset window
void render_gizmo_options();
// how the top view draws the tracks: as a combo with the colour of the rails, or as items of a menu
void render_top_tracks_choice(bool const Combo);
// the tools of the field of work in the toolbar under the menu
void render_toolbar();
// an edit mode of the node bank as the field of work, from the toolbar or its key (1-5)

View File

@@ -283,8 +283,8 @@ editor_mode::selftest_result editor_mode::selftest_scene(std::string const &comm
if (extent > 0.0f)
Global.EditorOrthoExtent = std::clamp(extent, 5.0f, 50000.0f);
if (false == ballast.empty())
Global.EditorOrthoBallast = ballast != "noballast";
WriteLog(format("SELFTEST ortho extent %.0f ballast %d", Global.EditorOrthoExtent, Global.EditorOrthoBallast ? 1 : 0));
Global.EditorOrthoTracks = ballast == "rails" ? 2 : ballast == "noballast" ? 1 : 0;
WriteLog(format("SELFTEST ortho extent %.0f tracks %d", Global.EditorOrthoExtent, Global.EditorOrthoTracks));
return selftest_result::handled;
}
if (command == "mapstate")

View File

@@ -15,6 +15,7 @@ http://mozilla.org/MPL/2.0/.
#include "application/editormodetrackshared.h"
#include "editor/editorFormat.hpp"
#include "editor/editorGeometry.hpp"
#include "editor/editorSettings.hpp"
#include "editor/editorSwitchStore.hpp"
#include "utilities/Globals.h"
@@ -201,14 +202,18 @@ void editor_mode::update_track_hover()
void editor_mode::draw_track_lines() const
{
auto const metres{ortho_metres_per_pixel()};
auto const colouring{m_track_colouring};
if (metres < kLinesFrom && colouring == track_colouring::plain)
auto const colouring{ui()->mode() == nodebank_panel::TRACK ? m_track_colouring : track_colouring::plain};
// the top view of the rails alone draws them in a colour of their own, as on a plan: both rails where they're apart on the screen
auto const rails{metres > 0.0 && Global.EditorOrthoTracks > 1 && colouring == track_colouring::plain};
if (metres < kLinesFrom && colouring == track_colouring::plain && false == rails)
return;
auto const &io{ImGui::GetIO()};
screen_projection const projection;
glm::dvec2 const centre{Global.pCamera.Pos.x, Global.pCamera.Pos.z};
auto const reach{Global.EditorOrtho ? 0.5 * metres * std::hypot(static_cast<double>(io.DisplaySize.x), static_cast<double>(io.DisplaySize.y)) : kColouredReach};
auto const width{colouring == track_colouring::plain ? 1.5f : 3.0f};
auto const width{rails ? std::max(2.0f, static_cast<float>(0.07 / metres)) : colouring == track_colouring::plain ? 1.5f : 3.0f};
auto const railcolour{EditorSettings.top_rails()};
std::vector<glm::dvec3> points;
auto *drawlist{ImGui::GetBackgroundDrawList(ImGui::GetMainViewport())};
for (auto *track : simulation::Paths.sequence())
{
@@ -220,7 +225,7 @@ void editor_mode::draw_track_lines() const
bezier const curve{path};
if (false == plan_near(curve, centre, reach))
continue;
auto colour{IM_COL32(235, 235, 235, 150)};
auto colour{rails ? railcolour : IM_COL32(235, 235, 235, 150)};
if (colouring == track_colouring::radius)
{
auto const radius{::track_mode::piece_plan_radius(path)};
@@ -229,7 +234,24 @@ void editor_mode::draw_track_lines() const
else if (colouring == track_colouring::speed)
colour = velocity > 0.0 ? band_colour(kSpeedBands, velocity) : kUncoloured;
auto const length{curve.plan_length(4)};
auto const count{std::clamp(static_cast<int>(length / std::max(metres, 0.5) / 8.0), colouring == track_colouring::grade ? std::clamp(static_cast<int>(length / 10.0), 1, 8) : 1, 32)};
auto const count{std::clamp(static_cast<int>(length / std::max(metres, 0.5) / 8.0), colouring == track_colouring::grade ? std::clamp(static_cast<int>(length / 10.0), 1, 8) : 1, rails ? 128 : 32)};
if (rails && track->fTrackWidth / metres > 6.0)
{
points.clear();
for (int k = 0; k <= count; ++k)
points.push_back(curve.point(static_cast<double>(k) / count));
auto const half{(track->fTrackWidth + 0.07) * 0.5};
auto const across = [&](std::size_t const K) {
auto const along{points[std::min(K + 1, points.size() - 1)] - points[K > 0 ? K - 1 : 0]};
auto const normal{glm::dvec3{-along.z, 0.0, along.x}};
auto const size{glm::length(normal)};
return size > 1e-9 ? normal * (half / size) : glm::dvec3{0.0};
};
for (auto const side : {-1.0, 1.0})
for (std::size_t k = 1; k < points.size(); ++k)
projection.line(drawlist, points[k - 1] + across(k - 1) * side, points[k] + across(k) * side, colour, width);
continue;
}
auto previous{curve.point(0.0)};
for (int k = 1; k <= count; ++k)
{