mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-26 18:14:55 +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:
@@ -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"));
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -109,7 +109,11 @@ bool editorSettings::load()
|
||||
else if (key == "track_tools_all")
|
||||
m_track_tools_more = (value == "1");
|
||||
else if (key == "top_ballast")
|
||||
m_top_ballast = (value == "1");
|
||||
m_top_tracks = value == "1" ? 0 : 1;
|
||||
else if (key == "top_tracks")
|
||||
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.rfind(origin_prefix, 0) == 0)
|
||||
@@ -158,7 +162,8 @@ bool editorSettings::save()
|
||||
stream << "first_steps " << (m_first_steps ? 1 : 0) << "\n";
|
||||
stream << "terrain_offer " << (m_terrain_offer ? 1 : 0) << "\n";
|
||||
stream << "track_tools_all " << (m_track_tools_more ? 1 : 0) << "\n";
|
||||
stream << "top_ballast " << (m_top_ballast ? 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 << std::fixed << std::setprecision(3);
|
||||
for (auto const &origin : m_orthophoto_origins)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
@@ -62,8 +63,10 @@ public:
|
||||
bool track_tools_more() const { return m_track_tools_more; }
|
||||
void track_tools_more(bool Show) { m_track_tools_more = Show; }
|
||||
// the ballast of the railway drawn in the top view
|
||||
bool top_ballast() const { return m_top_ballast; }
|
||||
void top_ballast(bool Show) { m_top_ballast = Show; }
|
||||
int top_tracks() const { return m_top_tracks; }
|
||||
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
|
||||
{
|
||||
@@ -86,7 +89,8 @@ private:
|
||||
bool m_first_steps{true};
|
||||
bool m_terrain_offer{true};
|
||||
bool m_track_tools_more{false};
|
||||
bool m_top_ballast{true};
|
||||
int m_top_tracks{0}; // the railway in the top view: whole, without the ballast, the rails alone
|
||||
std::uint32_t m_top_rails{0xffd246ff}; // colour of the rails alone, as ImGui keeps it: ABGR
|
||||
track_norms m_norms{track_norms::ask};
|
||||
};
|
||||
|
||||
|
||||
@@ -11472,3 +11472,30 @@ msgstr ": pozostałe stoją dalej niż 10 m od toru, przy torze z pojazdami albo
|
||||
|
||||
msgid " (layer \"%s\")"
|
||||
msgstr " (warstwa \"%s\")"
|
||||
|
||||
msgid "Tracks in the top view"
|
||||
msgstr "Tory w widoku z góry"
|
||||
|
||||
msgid "Whole"
|
||||
msgstr "Całe"
|
||||
|
||||
msgid "Without ballast"
|
||||
msgstr "Bez podsypki"
|
||||
|
||||
msgid "Rails only"
|
||||
msgstr "Same szyny"
|
||||
|
||||
msgid "The tracks as in the 3D view"
|
||||
msgstr "Tory jak w widoku 3D"
|
||||
|
||||
msgid "The rails and the sleepers, the ground under them shows"
|
||||
msgstr "Szyny i podkłady, spod nich widać teren"
|
||||
|
||||
msgid "The rails alone, without the sleepers and the timbers of the switches, as on a plan"
|
||||
msgstr "Same szyny, bez podkładów i podrozjazdnic, jak na planie"
|
||||
|
||||
msgid "How the top view draws the tracks"
|
||||
msgstr "Jak widok z góry rysuje tory"
|
||||
|
||||
msgid "The colour of the rails, to stand out on the imagery and the map"
|
||||
msgstr "Kolor szyn, żeby odcinały się od ortofotomapy i mapy"
|
||||
|
||||
@@ -54,7 +54,14 @@ editor_track_view_range(float const Range, bool const Apply)
|
||||
bool
|
||||
editor_ballast_hidden(TTrack const *Track, bool const Colour)
|
||||
{
|
||||
return Colour && EditorModeFlag && Global.EditorOrtho && false == Global.EditorOrthoBallast && (Track->iCategoryFlag & 15) == 1;
|
||||
return Colour && EditorModeFlag && Global.EditorOrtho && Global.EditorOrthoTracks > 0 && (Track->iCategoryFlag & 15) == 1;
|
||||
}
|
||||
|
||||
// ...or the sleepers and the timbers of the switches too, the rails alone as on a plan
|
||||
bool
|
||||
editor_sleepers_hidden()
|
||||
{
|
||||
return EditorModeFlag && Global.EditorOrtho && Global.EditorOrthoTracks > 1;
|
||||
}
|
||||
|
||||
// the top view draws the scenery as far as the tracks; its models keep their own ranges
|
||||
@@ -4701,6 +4708,7 @@ void opengl33_renderer::Render(scene::basic_cell::path_sequence::const_iterator
|
||||
switch( m_renderpass.draw_mode ) {
|
||||
case rendermode::color:
|
||||
case rendermode::reflections: {
|
||||
if( editor_sleepers_hidden() ) { break; }
|
||||
for( auto first { First }; first != Last; ++first ) {
|
||||
auto *track = *first;
|
||||
if( false == track->m_visible ) { continue; }
|
||||
|
||||
@@ -174,7 +174,7 @@ struct global_settings {
|
||||
float FieldOfView{ 45.f }; // vertical field of view for the camera. TODO: move it to the renderer
|
||||
bool EditorOrtho{ false };
|
||||
float EditorOrthoExtent{ 150.f };
|
||||
bool EditorOrthoBallast{ true }; // the ballast of the railway drawn in the top view of the editor
|
||||
int EditorOrthoTracks{ 0 }; // the railway in the top view of the editor: 0 whole, 1 without the ballast, 2 the rails alone
|
||||
GLint iMaxTextureSize{ 4096 }; // maksymalny rozmiar tekstury
|
||||
GLint iMaxCabTextureSize{ 4096 }; // largest allowed texture in vehicle cab
|
||||
int iMultisampling{ 2 }; // tryb antyaliasingu: 0=brak,1=2px,2=4px,3=8px,4=16px
|
||||
|
||||
Reference in New Issue
Block a user